eduCF#60 D. Magic Gems /// 矩阵快速幂
题目大意:
给定n m (1≤N≤1e18, 2≤M≤100)
一个魔法水晶可以分裂成连续的m个普通水晶
求用水晶放慢n个位置的方案modulo 1000000007 (1e9+7)
input
4 2
output
5
设1为魔法水晶 0为普通水晶
n=4 m=2有5种方案 即
1111、0011、1001、1100、0000
得到递推公式
当 i < m 时 dp[ i ] = 1
当 i >= m 时 dp[ i ] = dp[ i-1 ] + dp[ i-m ]
n的范围是1e18 构造矩阵用矩阵快速幂
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define LL long long #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define mem(i,j) memset(i,j,sizeof(i)) const int N=1e5+5; const int M=105; const int mod=1e9+7; LL n,m; struct MAT { LL a[M][M]; MAT(){ mem(a,0); } MAT operator*(MAT p) { MAT res; for(int i=0;i<M;i++) for(int j=0;j<M;j++) for(int k=0;k<M;k++) res.a[i][j]=(res.a[i][j]+a[i][k]*p.a[k][j])%mod; return res; } }; MAT mod_pow(MAT A,LL x) { MAT res; res.a[0][0]=1; while(x) { if(x&1) res=res*A; A=A*A; x>>=1; } return res; } int main() { while(~scanf("%I64d%I64d",&n,&m)) { MAT A,B; for(int i=0;i<m;i++) A.a[i][i+1]=1; A.a[0][0]=A.a[m-1][0]=1; B=mod_pow(A,n); printf("%I64d\n",B.a[0][0]); } return 0; }