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;
}

 

posted @ 2020-09-17 22:21  GoodVv  阅读(145)  评论(0编辑  收藏  举报