Yet Another Number Sequence CodeForces - 392C
原题链接
考察:矩阵快速幂
不是人可以想出来的思路....
思路:
当\(i^k\)的\(i\)很大,\(k\)又很小时,可以考虑二项式展开.
\[S_{i+1} = S_{i} +A_{i+1}
\]
\[A_{i+1} = (i+1)^k \times f_{i+1}
\]
然后将\((i+1)^k\)进行二进制拆分
后面懒得写了,我也是参考了大佬的博客,他写得很详细了,主要讲讲初始化f数组的时候,题目定义的斐波那契数列f[0] = 1,所以f数组的前\(2*k+1\)项都是1.
大佬的博客--->Go
Code
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 85,M=1000000007;
int a[N][N],f[N],k;
LL n,C[N][N];
void init()
{
for(int i=0;i<=k*2+1;i++) f[i] = 1;
for(int i=0;i<=k;i++)
for(int j=0;j<=i;j++)
{
if(i==j) C[i][j] = 1;
else C[i][j] = (C[i-1][j]+C[i-1][j-1])%M;
a[j][i] = C[i][j];
a[j+k+1][i] = C[i][j];
a[j][k+1+i] = C[i][j];
}
a[2*k+2][2*k+2] = 1;
a[k][2*k+2] = 1;
}
void mul(int f[],int a[][N])
{
int res[N] = {0};
for(int i=0;i<2*k+3;i++)
for(int j=0;j<2*k+3;j++)
res[i] = (res[i]+(LL)f[j]*a[j][i])%M;
memcpy(f,res,sizeof res);
}
void mul(int a[][N])
{
int res[N][N]= {0};
for(int i=0;i<2*k+3;i++)
for(int j=0;j<2*k+3;j++)
for(int s=0;s<2*k+3;s++)
res[i][j] = (res[i][j]+(LL)a[i][s]*a[s][j])%M;
memcpy(a,res,sizeof res);
}
int main()
{
scanf("%lld%d",&n,&k);
init();
while(n)
{
if(n&1) mul(f,a);
mul(a);
n>>=1;
}
printf("%d\n",f[2*k+2]);
return 0;
}