「題解」hdu 4549 M斐波那契數列
阿新 • • 發佈:2020-10-18
題目
\(f_0=a\)
\(f_1=b\)
\(f_i=f_{i-1}\times f_{i-2},i>1\)
求 \(f_n\)。
思路
\(f_0=a,f_1=b,f_2=ab,f_3=ab^2,f_4=a^2b^3,f_5=a^3b^5\)。
發現指數都是斐波那契數列中相鄰的兩個數,指數可以用矩陣快速冪加速遞推去求。
因為模數為 \(1e9+7\) 是個質數,可以用費馬小定理降冪。
Code
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> const int mod = 1000000007; int a, b, n; struct Matrix { int g[3][3]; Matrix() { memset(g, 0, sizeof g); } void one() { g[1][1] = g[2][2] = 1; } friend Matrix operator * (Matrix m1, Matrix m2) { Matrix ans; for (int k = 1; k <= 2; ++k) { for (int i = 1; i <= 2; ++i) { for (int j = 1; j <= 2; ++j) { ans.g[i][j] = (ans.g[i][j] + (1ll * m1.g[i][k] * m2.g[k][j] % (mod - 1))) % (mod - 1); } } } return ans; } }tra, res, f; Matrix qpow(Matrix a, int b) { Matrix ans, base = a; ans.one(); while (b) { if (b & 1) ans = ans * base; base = base * base; b >>= 1; } return ans; } int qp(int a, int b) { int ans = 1, base = a; while (b) { if (b & 1) ans = 1ll * ans * base % mod; base = 1ll * base * base % mod; b >>= 1; } return ans; } int main() { while (scanf("%d %d %d", &a, &b, &n) != EOF) { if (n == 0) { printf("%d\n", a); continue; } tra.g[1][1] = tra.g[1][2] = tra.g[2][1] = 1, tra.g[2][2] = 0; f.g[1][1] = 1, f.g[2][1] = res.g[1][1] = res.g[2][1] = 0; tra = qpow(tra, n - 1); for (int k = 1; k <= 2; ++k) { for (int i = 1; i <= 2; ++i) { for (int j = 1; j <= 1; ++j) { res.g[i][j] = (res.g[i][j] + (1ll * tra.g[i][k] * f.g[k][j] % (mod - 1))) % (mod - 1); } } } printf("%lld\n", (1ll * qp(a, res.g[2][1]) * qp(b, res.g[1][1])) % mod); } return 0; }