HDU 4549 M斐波那契數列 (費馬小定理降冪&矩陣快速冪)
阿新 • • 發佈:2019-02-11
Problem Description
M斐波那契數列F[n]是一種整數數列,它的定義如下:
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )
現在給出a, b, n,你能求出F[n]的值嗎?
Input 輸入包含多組測試資料;
每組資料佔一行,包含3個整數a, b, n( 0 <= a, b, n <= 10^9 )
Output 對每組測試資料請輸出一個整數F[n],由於F[n]可能很大,你只需輸出F[n]對1000000007取模後的值即可,每組資料輸出一行。
Sample Input 0 1 0 6 10 2
Sample Output 0 60
Source
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )
現在給出a, b, n,你能求出F[n]的值嗎?
Input 輸入包含多組測試資料;
每組資料佔一行,包含3個整數a, b, n( 0 <= a, b, n <= 10^9 )
Output 對每組測試資料請輸出一個整數F[n],由於F[n]可能很大,你只需輸出F[n]對1000000007取模後的值即可,每組資料輸出一行。
Sample Input 0 1 0 6 10 2
Sample Output 0 60
Source
思路:
1. 首先得出封閉形式:
F[n]=a (n=0)
F[n]=a^Fib[n-1]*b^Fib[n] (n>0)
2. 發現1000000007是質數,遂用費馬小定理,得
F[n]%m=a^(Fib[n-1]%(m-1))*b^(Fib[n]%(m-1))%m
3. f[n]%(m-1)的計算用矩陣快速冪
4. a^x的計算用快速冪
完整程式碼:
/*0ms,232KB*/ #include<cstdio> const long long M = 1000000007; struct Matrix { long long mat[2][2]; }; const Matrix P = { 1, 1, 1, 0, }; const Matrix I = { 1, 0, 0, 1, }; Matrix matrixmul(Matrix a, Matrix b) { Matrix c; int i, j, k; for (i = 0 ; i < 2; ++i) for (j = 0; j < 2; ++j) { c.mat[i][j] = 0; for (k = 0; k < 2; ++k) ///利用費馬小定理 c.mat[i][j] += a.mat[i][k] * b.mat[k][j] % (M - 1);///行*列 c.mat[i][j] %= (M - 1); } return c; } ///P^n%(M-1),P已在程式開頭定義 Matrix quickpow(long long n) { Matrix m = P, ret = I; while (n) { if (n & 1) ret = matrixmul(ret, m); n >>= 1; m = matrixmul(m, m); } return ret; } ///a^b%M long long quickpow(long long a, long long b) { long long ret = 1; while (b) { if (b & 1) ret = ret * a % M; b >>= 1; a = a * a % M; } return ret; } int main() { long long a, b, n; Matrix q; while (~scanf("%I64d%I64d%I64d", &a, &b, &n)) { q = quickpow(n);///不需要特判哦 printf("%I64d\n", quickpow(a, q.mat[1][1]) * quickpow(b, q.mat[1][0]) % M);///a^Fib(n-1)*b^Fib(n)%M } return 0; }