1. 程式人生 > >簡單遞推公式轉換矩陣求解

簡單遞推公式轉換矩陣求解

 對於許多遞推題目,由於資料範圍太大直接迴圈寫會爆掉,這時首先想到的就是矩陣優化,把遞推式轉換成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; }