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