P1306 斐波那契公约数
首先:
F[1] = F[1] = 1
F[i] = F[i - 1] + F[i - 2] (i > 2)
假设n > m
设 F[m] = a , F[m + 1] = b
F[m + 2] = a + b
F[m + 3] = a + b * 2 = a + F[3] * b
F[m + 4] = 2 * a + 3 * b = F[3] * a + F[3] * (F[3] + F[2]) * b = F[3] * a + F[4] * b
F[m + 5] = (F[3] + F[2]) * a + (F[4] + F[3]) * b = F[4] * a + F[5] * b
........
F[n] = F[n - m - 1] * F[m] + F[n - m] * F[m + 1]
所以GCD(F[n] , F[m]) = GCD(F[n - m - 1] * F[m] + F[n - m] * F[m + 1],F[m])
由于F[n - m - 1] * F[m] 是 F[m] 的倍数,所以去掉
就变成了GCD(F[n] , F[m]) = GCD(F[n - m - 1] * F[m] + F[n - m] * F[m + 1],F[m]) = GCD(F[n - m] * F[m + 1] , F[m])
由于GCD(F[m + 1] , F[m]) = 1 , 所以GCD(F[n - m] * F[m + 1] , F[m]) = GCD(F[n - m] , F[m])
也就是:
GCD(F[n] , F[m]) = GCD(F[n - m] , F[m]) = GCD(F[n - 2 * m] , F[m]) = ....
然后通过不挺的执行以上操作就会变成:
GCD(F[n] , F[m]) = GCD(F[n % m] , F[m])
接下来设mm = n % m , 同样进行操作,就变成了:
GCD(F[n % m] , F[m]) = GCD(F[mm] , F[m % mm]) ....
这么一看其实就是辗转相除,当其中有一个变为0的时候,另外一个不为0的就是答案了
也就是F[GCD(n ,m)]
矩阵快速幂一波就好了
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6 + 10; #define ll long long #define int long long int gcd(int a,int b){return !b?a:gcd(b,a%b);} const int MAXN = 2; struct Matrix { ll mat[MAXN][MAXN]; }; Matrix P; Matrix I; //单位矩阵 Matrix Mul_Matrix(Matrix a, Matrix b , ll mod) { Matrix c; for(int i = 0 ; i < MAXN ; i ++) for(int j = 0 ; j < MAXN ; j ++) { c.mat[i][j] = 0; for(int k = 0 ; k < MAXN ; k ++) { c.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % mod; c.mat[i][j] %= mod; } } return c; } Matrix pow_mod_Matrix(Matrix P , ll n , ll mod) { Matrix ans = I, b = P; while(n) { if(n & 1) ans = Mul_Matrix(ans , b , mod); n >>= 1; b = Mul_Matrix(b , b , mod); } return ans; } void Matrix_init() { for(int i = 0 ; i < MAXN ; i ++) I.mat[i][i] = 1; P.mat[0][0] = P.mat[0][1] = P.mat[1][0] = 1; } const int mod = 1e8; signed main() { ios; cin.tie(0); int n , m; cin >> n >> m; Matrix_init(); int re = gcd(n , m); if(re <= 2) cout << "1\n"; else cout << pow_mod_Matrix(P , re - 1 , mod).mat[0][0] << '\n'; return 0; }