题目大意:给你一个数列a,规定$a[1]=a[2]=a[3]=1$,$a[i]=a[i-1]+a[i-3](i>3)$求$a[n] mod 10^9+7$的值。
解题思路:这题看似是很简单的递推,但是$nleq 2×10^9$,递推肯定是会超时的。故我们需要优化。
常见优化有矩阵加速,还有什么我并不知道了。
用矩阵可将此类题目时间复杂度从$O(n)$优化为$O(log_2 n)$。
具体对于此类形如$f(n)=f(n-1)*p(1)+f(n-2)*p(2)+...+f(n-k)*p(k)$的线性递推问题,有如下解法。
设$F[i]=egin{bmatrix} fn-k] \f[n-k+1]\f[n-k+2]\...\f[n-1]\f[n] end{bmatrix}quad$,
则$F[n]=egin{bmatrix} 0&1&0&0&...&0\0&0&1&0&...&0\0&0&0&1&...&0\...&...&...&...&...&...\0&0&0&0&...&1\p[k]&p[k-1]&p[k-2]&p[k-3]&...&p[1]end{bmatrix}quad ×F[n-1]$。
运用矩阵快速幂即可完成加速。
故此题解法如下。
$$egin{bmatrix}a[n-2]\a[n-1]\a[n]end{bmatrix}quad =egin{bmatrix}0&1&0\0&0&1\1&0&1end{bmatrix}^{n-3}quad×egin{bmatrix}a[1]\a[2]\a[3]end{bmatrix}quad$$
C++ Code:
#include<cstdio> #include<cstring> using namespace std; struct mat{ long long a[30][30]; int r,c; }; mat mul(mat x,mat y){ mat ans; memset(&ans,0,sizeof ans); for(int i=0;i<x.r;++i) for(int j=0;j<y.c;++j) for(int k=0;k<x.c;++k) ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j])%1000000007; ans.r=x.r; ans.c=y.c; return ans; } void pow(int n){ mat p; memset(&p,0,sizeof p); p.r=p.c=3; p.a[0][1]=p.a[1][2]=p.a[2][0]=p.a[2][2]=1; mat ans; memset(&ans,0,sizeof ans); ans.r=ans.c=3; ans.a[0][0]=ans.a[1][1]=ans.a[2][2]=1; while(n){ if(n&1){ ans=mul(p,ans); } p=mul(p,p); n>>=1; } p.a[0][0]=p.a[1][0]=p.a[2][0]=1; p.c=1; ans=mul(ans,p); printf("%d ",(int)ans.a[2][0]); } int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); if(n<4)puts("1");else pow(n-3); } return 0; }