P1306 斐波那契公约数
Posted lltyyc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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_{gcd(n,m)},f_{gcd(n,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; }
以上是关于P1306 斐波那契公约数的主要内容,如果未能解决你的问题,请参考以下文章