洛谷 P1306 斐波那契公约数

洛谷

这道题只要知道这个公式就可以秒切了。$$gcd(f[n],f[m])=f[gcd(n,m)]$$

具体怎么做呢?

看到数据范围,\(10^9\),所以要用矩阵快速幂。

直接先求\(gcd(n,m)\),令其等于\(t\),然后在用矩阵就出\(f[t]\)

矩阵应该不用讲吧,直接给出来。

\[\begin{matrix} 1&1\\ 1&0\\ \end{matrix}\]

当然,矩阵乘法的过程中需要不断对\(10^8\)取模,因为要求输出后\(8\)位。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;

const int m=100000000;
ull n,f[3]={0,1,1},t[3][3]={
{0,0,0},
{0,0,1},
{0,1,1}
};

ull suan(ull x,ull y)
{
    ull ans=0;
    while (y) {
        if (y&1) ans=(ans%m+x%m)%m;
        y>>=1;x=(x%m+x%m)%m;
    }
    return ans%m;
}

void fuyan()
{
    ull d[3];
    memcpy(d,f,sizeof(d));
    memset(f,0,sizeof(f));
    for (int i=1;i<=2;++i)
        for (int j=1;j<=2;++j)
            f[i]=(f[i]%m+suan(d[j]%m,t[j][i]%m))%m;
}

void yuzhouzhou()
{
    ull d[3][3];
    memcpy(d,t,sizeof(d));
    memset(t,0,sizeof(t));
    for (int i=1;i<=2;++i)
        for (int j=1;j<=2;++j)
            for (int k=1;k<=2;++k)
                t[i][j]=(t[i][j]%m+suan(d[i][k]%m,d[k][j]%m))%m;
}

int main()
{
    ull a,b;
    cin>>a>>b;
    while (b^=a^=b^=a%=b);
    n=a;
    if (n<3) {cout<<f[n];return 0;}
    n-=2;
    while (n) {
        if (n&1) fuyan();
        yuzhouzhou();n>>=1;
    }
    cout<<f[2];
    return 0;
}
posted @ 2018-09-08 07:54  fuyan0101  阅读(144)  评论(0编辑  收藏  举报