对于许多递推题目,由于数据范围太大直接循环写会爆掉,这时首先想到的就是矩阵优化,把递推式转换成01矩阵通过快速幂优化。
比如最简单的斐波纳挈,如果n非常大,循环递推肯定是不合适的,那么可以考虑下面的公式 (f[n],f[n-1])=(f[n-1],f[n-2])*A; 这里的A是一个01矩阵,此时的A={1,1,1,0} 2*2的矩阵, 可想而知 f[3] = A的n-2次幂*(f[2],f[1]); 形如斐波纳挈的递推公式转换矩阵都很简单, 顺便附上POJ3070的 斐波纳挈转矩阵快速幂的代码
#include<cstdio> #include<cstring> #include<iostream> #define MOD 10000 using namespace std; struct mac { int frob[2][2]; }pri,unit; mac power(mac x,mac y) { mac temp; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { temp.frob[i][j]=0; for(int k=0;k<2;k++) { temp.frob[i][j]=(temp.frob[i][j]+x.frob[i][k]*y.frob[k][j])%MOD; } } } return temp; } void eachother(int n) { pri.frob[0][0]=pri.frob[0][1]=pri.frob[1][0]=1; pri.frob[1][1]=unit.frob[0][1]=unit.frob[1][0]=0; unit.frob[0][0]=unit.frob[1][1]=1; while(n) { if(n&1) { unit = power(unit,pri); } pri = power(pri,pri); n >>= 1; } printf("%d\n",unit.frob[0][1]); } int main() { int n; while(scanf("%d",&n)!=EOF) { if(n==-1) break; if(n==0) { printf("0\n"); continue; } if(n==1||n==2) { printf("1\n"); continue; } eachother(n); } return 0; }
时间: 2024-11-07 06:55:49