Magic Gems(递推+矩阵快速幂优化)

题面

Reziba has many magic gems. Each magic gem can be split into M normal gems. The amount of space each magic (and normal) gem takes is 1 unit. A normal gem cannot be split.

Reziba wants to choose a set of magic gems and split some of them, so the total space occupied by the resulting set of gems is N units. If a magic gem is chosen and split, it takes MM units of space (since it is split into M gems); if a magic gem is not split, it takes 1 unit.

How many different configurations of the resulting set of gems can Reziba have, such that the total amount of space taken is N units? Print the answer modulo 1000000007 ( 1 0 9 10^9 109+7). Two configurations are considered different if the number of magic gems Reziba takes to form them differs, or the indices of gems Reziba has to split differ.

Input

The input contains a single line consisting of 2 integers N and M ( 1 ≤ N ≤ 1 0 18 , 1 ≤ N ≤ 1 0 18 , 2 ≤ M ≤ 100 , 2 ≤ M ≤ 100 ) . (1 \le N \le 10^{18} ,1 ≤N≤10^{18}, 2 \le M \le 100,2≤M≤100). (1≤N≤1018,1≤N≤1018,2≤M≤100,2≤M≤100).

Output

Print one integer, the total number of configurations of the resulting set of gems, given that the total amount of space taken is N units. Print the answer modulo 1000000007 ( 1 0 9 10^9 109+7).

样例输入输出

Input

4 2

Output

5

Input

3 2

Output

3

Note

In the first example each magic gem can split into 2 normal gems, and we know that the total amount of gems are 4.

Let 1 denote a magic gem, and 0 denote a normal gem.

The total configurations you can have is:

  • 1111 (None of the gems split);
  • 0011 (First magic gem splits into 2 normal gems);
  • 1001 (Second magic gem splits into 2 normal gems);
  • 1100 (Third magic gem splits into 2 normal gems);
  • 0000 (First and second magic gems split into total 4 normal gems).

Hence, answer is 5.

题意:

(不得不说这题的题意真的很难理解)

Two configurations are considered different if the number of magic gems Reziba takes to form them differs, or the indices of gems Reziba has to split differ.

对于以上这句话我也是反复翻译却依旧不能理解

后来突然发现,这其实就是挨个取魔法石并判断是否分裂的过程

就拿note中的例子说(n=2,m=4):

1、1111 是指,每次取一个石头,每次都不分裂

2、0011 是指,取第一个石头,使其分裂,再取两个石头补满4个

3、1001 是指,取第一个石头,不分裂,取第二个石头,分裂,再取一个石头并不分裂,补满4个

4、1100 是指,取两个石头不分裂,再取一个石头分裂

5、0000 是指,先后取两个石头都分裂

这么理解就能完美解释note,并且也能解释两个样例输入输出

再一想,这题其实就有点像dp,取一个石头,判断是否分裂

如果我们设f[i] 为空间为i时的排列种类

那么其实f[i]=f[i-1]+f[i-m]就应该成立

因为我们取一个石头要判断是否分裂,如果分裂他的大小就为m,不分裂他的大小就为1

那我们只要知道空间为(i-m)时的排列种类f[i-m]和空间为(i-1)时的排列种类f[i-1]并将其累加就是取当前石头所有可能的情况

以此递推的话,答案很显然就是f[n]—— 即空间为n时所有的排列情况

矩阵推导

f(i) f(i-1)
f(i-1) f(i-2)
f(i-2) f(i-3)
f(i-m+2) f(i-m+1)
f(i-m+1) f(i-m)

左边就是需要递推出来的下一项

右边则是前一项

因为f(i)=f(i-1)+f(i-m) 所以转换矩阵的第一行的第一个数据与最后一个数据都是1,第一行其余都是0

之后可以发现从右边的第二行到倒数第二行和左边的第三行到最后一行,都存在一个倾斜的对于关系,只要在转换矩阵中适当赋1将其递推过去就行

于是我们得出

但是要注意,递推起点的初值,只有f(0)是有意义的,f(-1)f(-2)都是没有意义的

所以我们的递推起点的向量应该是{ f(m-1) , f(m-2) ,… f(0) }

所以递推次数应该是(m-1)

再用矩阵快速幂就能解决

贴上AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod = 1e9 + 7;
template <typename T>
void read(T &x)
{x = 0;char ch = getchar();ll f = 1;while (!isdigit(ch)){if (ch == '-')f *= -1;ch = getchar();}while (isdigit(ch)){x = x * 10 + ch - 48;ch = getchar();}x *= f;
}
ll t, n, m;
const ll N = 109;
ll a[N][N], f[N];void mul(ll a[109][109], ll f[109]) // m ^ 2
{ll c[109];memset(c, 0, sizeof(c));for (int i = 0; i < m; i++){for (int j = 0; j < m; j++){c[i] = ((ll)c[i] + (ll)f[j] * (ll)a[j][i]) % mod;}}memcpy(f, c, sizeof(c));
}
void mulself(ll a[109][109]) // m^3
{ll c[109][109];memset(c, 0, sizeof(c));for (int i = 0; i < m; i++){for (int j = 0; j < m; j++){for (int k = 0; k < m; k++){c[i][j] = ((ll)c[i][j] + (ll)a[i][k] * (ll)a[k][j]) % mod;}}}memcpy(a, c, sizeof(c));
}int main()
{read(n);read(m);a[0][0] = a[0][m - 1] = 1;for (int j = 1; j < m; j++){a[j][j - 1] = 1;}for (int i = 0; i <= m - 1; i++){f[i] = 1;}n -= (m - 1);n = max(0ll, n);for (; n; n >>= 1){if (n & 1)mul(a, f);mulself(a);}printf("%lld\n", f[0]);return 0;
}
/*
+───────────+─────────────+
| f[0]      | f[n]        |
+───────────+─────────────+
| f[1]      | f[n-1]      |
| ...       | ...         |
| ...       | ...         |
| ...       | ...         |
| f[m - 1]  | f[n-m + 1]  |
|           |             |
|           |             |
|           |             |
|           |             |
+───────────+─────────────+
*/

如果有问题欢迎指出

Magic Gems魔法石相关推荐

  1. 哈里波特与魔法石pdf_哈里·罗伯茨(CSS)CSS框架的命运与失败

    哈里波特与魔法石pdf Harry Roberts helps teams all over the world to build better front ends. Craig spoke to ...

  2. 《哈利波特与魔法石》英文版读书笔记:目光实体化

    在我小学的时候,我有幸接触到了哈利波特系列小说.后来陆续陆续读完了全部七本.再后来重新阅读了一遍. 众所周知,阅读英文技术文档是诸位程序员的一个必备技能.我在休闲时间阅读哈利波特的英文原著,正是基于这 ...

  3. ESR五部曲之五——The Magic Cauldron 魔法大熔炉

    魔法大锅炉 Eric S. Raymond五部曲之The Magic Cauldron 魔法大锅炉 -- 前言.目录 Eric Raymond (1999年六月) [AKA]rover HansB i ...

  4. D. Magic Gems

    http://codeforces.com/contest/1117/problem/D 题意:n,m(1e18) :有一些魔法石,一个魔法石可以分裂成m个普通宝石,每个宝石站一个单位空间:问有多少集 ...

  5. 问题 G: Heartlessly 的魔法石

    问题 G: Heartlessly 的魔法石 时间限制: 1 Sec 内存限制: 128 MB 题目描述 Heartlessly 有 n 个魔法石,每个魔法石都有对应的魔法值(用正整数 a i 表示) ...

  6. 个人笔记:算法讲座3.2——魔法石(棋盘最优路径)

    本文仅供学习参考使用,谢谢 目录 问题描述: 思路分析: 算法描述: 测试数据: 递推: 递归: 问题描述: 霍格沃茨魔法学校的密室里有一个巨大的棋盘,棋盘有n * n个格子,Alice丢失了魔杖被伏 ...

  7. 读《哈利波特与魔法石》有感

    花了几天晚上粗略地看完小说<哈利波特与魔法石>(哈利1)一遍了.虽然事先看了wiki关于<死亡圣器>的剧透,不过觉得第一部已经写得很有气势了(不像是面向儿童的读物).觉得哈利波 ...

  8. 牛客OI周赛6-提高组 A 大法师与魔法石

    大法师与魔法石 思路: 对于一个ai, 它可以构成区间[ai/v, ai] 假设和它相邻的为aj, 那么ai 和 aj 构成的区间为[(ai+aj) / v, ai+aj] 那么这两个区间能合并的条件 ...

  9. 个人日记—《哈利波特与魔法石》电影观后感—20200816

    个人日记-<哈利波特与魔法石>电影观后感-20200816 这周看了电影<哈利波特与魔法石>,这部电影是重映的,说明这部电影还是不错的. (1)斯内普-坏人与好人 这部电影中, ...

最新文章

  1. 制作npm插件vue-toast-m实例练习
  2. Python超详细的字符串用法大全
  3. linux下面升级 Python版本并修改yum属性信息
  4. LeetCode刷题(32)
  5. OpenCV 访问Mat 像素
  6. ipsec over gre与gre over ipsec
  7. java中的T extends Comparable ? super T
  8. php代码,IP地址归属地批量查询功能
  9. Java删除文件夹下所有文件
  10. matlab脉冲调制,基于matlab脉宽调制方法的研究
  11. python试卷河南理工大学官网_河南理工大学试卷模板
  12. python-docx页眉横线
  13. python函数里调用外部变量
  14. 计算机桌面怎样创建文件,如何在电脑桌面新建一个透明文件夹
  15. 微软Windows 8 非常实用的12个技巧
  16. 自然语言处理NLP简介
  17. java实现美图秀秀的照片拼接功能(照片数量任意)
  18. FTT价值评估报告 | TokenInsight
  19. Linux常用的远程工具
  20. 关于MNN中图像预处理

热门文章

  1. am335x linux内核烧写_am335x文件系统烧写问题
  2. 计算机考研多少是高分,考研多少分算高分 总分500考380难吗
  3. USB电源过流保护芯片应用介绍
  4. 换了5G手机不会用5G网络?赶快来补课!
  5. adb 出现多个设备情况操作解决
  6. 使用QueryList解析微信文章
  7. Android绘制颜色渐变图形
  8. 首批接入司法数据的网贷平台已拒贷3万余失信被执行人
  9. [递推] 51Nod1383 整数分解为2的幂
  10. Android开源的社交应用