【hdu4549 M斐波那契數列】【矩陣快速冪】【F[n] = F[n-1] * F[n-2] ,求F[n] 】
阿新 • • 發佈:2018-12-13
【連結】
【題意】
F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 給出a, b, n,求出F[n]
【分析】
寫出幾項後,發現:F[n]=a^x*b^y,x,y成斐波那契數列。
且有規律:ans=a^(F[n-1])*b^(F[n])
斐波那契數列F[]陣列可通過矩陣快速冪n^3logk求解,但是由於n很大,繼續直接求解會超時。
由費馬小定理a^(p-1)+1==0(mod p).繼續求解時可以簡化冪上(p-1)得迴圈節。
【程式碼】
#include<bits./stdc++.h> using namespace std; using ll = long long; const int maxn = 1000006; const int mod = 1e9 + 7; ll F[maxn]; ll a, b, n; ll qpow2(ll a, ll b) { ll res = 1; ll ans = a % (mod); while (b) { if (b & 1) res = res * ans%(mod); ans = ans * ans%(mod); b >>= 1; } return res; } struct ma { ll m[2][2]; }; ma mul(ma a, ma b) { ma c; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { c.m[i][j] = 0; for (int k = 0; k < 2; k++) { c.m[i][j] += (a.m[i][k] * b.m[k][j]) % (mod-1); } c.m[i][j] %= (mod-1); } } return c; } ma qpow1(ma a, ll n) { ma ans = { 1,0,0,1 }; ma res = a; while (n) { if (n & 1)ans = mul(ans, res); res = mul(res, res); n >>= 1; } return ans; } int main() { ma tmp = { 0,1,1,1 }; while (~scanf("%lld%lld%lld", &a, &b, &n)) { ma p = qpow1(tmp, n); printf("%lld\n", qpow2(a, p.m[0][0])*qpow2(b, p.m[0][1]) % mod); } }