一道递推题目
得到递推关系为 f[n]=f[n-1]+f[n-3]+f[n-4];
用普通的枚举算法会超时
所以要用矩阵快速幂来加速
转化为矩阵即为:
+
1 0 1 1 F(N-1) F(N)
1 0 0 0 * F(N-2) = F(N-1)
0 1 0 0 F(N-3) F(N-2)
0 0 1 0 F(N-4) F(N-3)
1 0 1 1(n-4) F(4) F(N)
1 0 0 0 * F(3) = F(N-1)
0 1 0 0 F(2) F(N-2)
0 0 1 0 F(1) F(N-3)
所以f(n) 为 矩阵的n-4次幂 的第一行 与已知的相乘 (n-4 为 n-3-1即可 这是差值 再加一为个数)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,k; int q[5]={0,2,4,6,9}; struct matrix{ int arr[4][4]; }; matrix multi( matrix a,matrix b ) { matrix c; for(int i=0;i<4;i++) for(int j=0;j<4;j++){ c.arr[i][j]=0; for(int w=0;w<4;w++) c.arr[i][j]=(c.arr[i][j]+a.arr[i][w]*b.arr[w][j]%k)%k; } return c; } int fast(matrix a,int x){ matrix ans; memset(ans.arr,0,sizeof(ans.arr)); for(int i=0;i<4;i++)ans.arr[i][i]=1; while(x){ if(x&1){ ans=multi(ans,a); } x>>=1; a=multi(a,a); } int sum=0; for(int i=0;i<4;i++) { sum+=ans.arr[0][i]*q[4-i]; sum%=k; } return sum; } int main(){ while(scanf("%d%d",&n,&k)==2) { if(n<=4){printf("%d ",q[n]%k);continue;} else { matrix a={1,0,1,1,1,0,0,0,0,1,0,0,0,0,1,0}; printf("%d ",fast(a,n-4)%k); } } return 0; }
矩阵还是用结构体写方便。