矩陣快速冪法+斐波那契數列餘數
阿新 • • 發佈:2018-12-24
#include<stdio.h> struct mar { long long a[2][2]; }; mar mar_mul(mar x,mar y); int Fmod(long long n); int main() { int t,i; long long b[100]; scanf("%d",&t); for(i=0;i<t;i++) scanf("%lld",&b[i]); for(i=0;i<t;i++) printf("%d\n",Fmod(b[i])); return 0; } mar mar_mul(mar x,mar y) { mar latest; latest.a[0][0]=(x.a[0][0]*y.a[0][0]+x.a[0][1]*y.a[1][0])%100000007;//此步驟見下方詳解 latest.a[0][1]=(x.a[0][0]*y.a[0][1]+x.a[0][1]*y.a[1][1])%100000007; latest.a[1][0]=(x.a[1][0]*y.a[0][0]+x.a[1][1]*y.a[1][0])%100000007; latest.a[1][1]=(x.a[1][0]*y.a[0][1]+x.a[1][1]*y.a[1][1])%100000007; return latest; } int Fmod(long long n) { long long N=n-1; int ans; mar res,f; res.a[0][0]=1; res.a[0][1]=0; res.a[1][0]=0; res.a[1][1]=1; f.a[0][0]=1; f.a[0][1]=1; f.a[1][0]=1; f.a[1][1]=0; while(N>0) { if(N%2!=0) res=mar_mul(res,f); N/=2; f=mar_mul(f,f); } return res.a[0][0]; }
快速冪取模演算法的原理為ac%b=(a%b)*(c%b)
此處矩陣快速冪與之相似,但由於有了加法導致理解困難,事實上我們可以證明對於有限次四則運算該演算法都是正確的,由於斐波那契數列“公比”矩陣為[1 1\n1 0],對於一開始的四個元素,必定是小於題目要求的除數,在上述程式碼中為100000007,故%運算子對其無影響,而對於之後得到的矩陣來說,每個元素必定由之前矩陣的元素經過有限次四則運算得到的,又由於((a%mod)*(b%mod)+(c%mod)*(d%mod))%mod=(a*b%mod+c*d%mod)%mod=(ab+cd)%mod,故只需對矩陣每一個元素關於mod取餘,最後即可得到斐波那契數列的第n項對mod取餘的結果。