1. 程式人生 > >HDU 4549 M斐波那契數列 (矩陣快速冪+費馬小定理)

HDU 4549 M斐波那契數列 (矩陣快速冪+費馬小定理)

思路:

通過列出幾項我們就可以發現ab的指數是斐波那契數列。然後博主就開(智)心(障)的用矩陣快速冪算指數了。。
卻忘了一件事。。。誰說的取模對指數封閉的啊???md瘋狂wa了六七次。
取模對乘法封閉但不意味著指數你可以直接取模啊。。

正解是根據費馬小定理:

ab=cmodp

gcd(a,p)=1 並且p是素數的時候,有:ap1=1modp 也就是說,指數上迴圈節為0 1 2 。。。。p-1,所以我們可以對指數模(1e9+7-1)。

好了,結果出來了。

#include <cstdio>
#include <iostream>
#include <string.h>
#include <queue> #include <algorithm> typedef long long int lli; using namespace std; const int mod = 1000000007; const int n = 2; struct mat{ lli ma[n][n]; }; mat operator * (mat &a,mat &b){ mat c; const int mm = mod-1; memset(c.ma,0,sizeof(c.ma)); for(int k=0;k<n;++k){ for
(int i=0;i<n;++i){ for(int j=0;j<n;++j){ c.ma[i][j] += a.ma[i][k]%mm*(b.ma[k][j]%mm)%mm; c.ma[i][j] %= mm; } } } return c; } mat qp(mat a,lli k){ mat c; for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ c.ma
[i][j] = (i==j); } } for(;k;k>>=1){ if(k&1) c=c*a; a = a*a; } return c; } lli qp(lli a,lli x){ lli res = 1;a %= mod; for(;x;x>>=1){ if(x&1){ res *= a;res %= mod; } a = a*a%mod; } return res; } int main(){ int a,b,n; while(~scanf("%d%d%d",&a,&b,&n)){ mat zuo = {1,0, 0,0}; mat base = {1,1, 1,0}; if(n == 0){ printf("%d\n",a%mod); continue; } else{ base = qp(base,n-1); lli a1 = base.ma[0][1],b1 = base.ma[0][0]; lli ans = qp(a,a1)%mod; ans = (ans*qp(b,b1))%mod; printf("%lld\n",ans); } } }