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;
}
posted @ 2021-06-09 14:00  acmloser  阅读(27)  评论(0编辑  收藏  举报