P1306 斐波那契公约数

传送门

直接搞肯定不行(题目清清楚楚写了)

所以开始要推结论

设 $f_a = x$ , $f_{a+1} = y$ 那么 $f_{a+2}=x+y,f_{a+3}=x+2y,f_{a+4}=2x+3y$ ....

最终可以得到一个通用公式,$f_n = f_{n-a-1}f_a + f_{n-a}f_{a+1} (n≥a+2)$

那么对于 $f_n$ 与 $f_m$ ,不妨设 n>=m+2

那么 $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) $,

根据辗转相减法,$gcd(f_{n-m-1}f_m + f_{n-m}f_{m+1},f_m) = gcd(f_{n-m}f_{m+1},f_m)$

(前一项减去$f_{n-m-1}$个$f_m$)

因为 $f_m$ 与 $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,f_m) = f_{gcd(n,m)}$

容易证明, n=m+1 和 n=m 的情况也一样成立

所以就是求 $f_{gcd(n,m)}$ 的后八位数

但是最坏情况 $gcd(n,m)$ 可能大于$10^9$ ,所以要用矩阵加速一下

代码很简单,就不注释了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int mo=1e8;
int n,m,d;
inline int gcd(int a,int b) { return b ? gcd(b,a%b) : a; }
inline int fk(int x) { return x>=mo ? x-mo : x; }
struct matrix
{
    int a[2][2];
    matrix () { memset(a,0,sizeof(a)); }
    inline matrix operator * (matrix &tmp) {
        matrix res;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                for(int k=0;k<2;k++) res.a[i][j]=fk(res.a[i][j]+(1ll*a[i][k]*tmp.a[k][j])%mo);
        return res;
    }
}M,A;
int main()
{
    M.a[0][0]=M.a[0][1]=1; A.a[0][1]=A.a[1][0]=A.a[1][1]=1;
    n=read(); m=read(); d=gcd(n,m); d--;
    while(d)
    {
        if(d&1) M=M*A;
        A=A*A; d>>=1;
    }
    printf("%d",M.a[0][0]);
    return 0;
}

 

posted @ 2018-10-27 11:43  LLTYYC  阅读(182)  评论(0编辑  收藏  举报