题目描述
对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少?
Update:加入了一组数据。
输入格式
两个正整数n和m。(n,m<=10^9)
注意:数据很大
输出格式
Fn和Fm的最大公约数。
由于看了大数字就头晕,所以只要输出最后的8位数字就可以了。
输入输出样例
输入 #1
4 7
输出 #1
1
说明/提示
用递归&递推会超时
用通项公式也会超时
题解
一个结论 GCD(f[n] , f[m]) = f[GCD(n , m)];
证明
设 n < m , f[n] = a , f[n+1] = b;
那么f[m] = f[m-n-1]×a + f[m-n]×b;
f[m] = f[m-n-1]×f[n] + f[m-n]×f[n+1];
gcd(f[n] , f[m]) = gcd(f[n] , f[m-n-1] × f[n] + f[m-n] × f[n+1]);
因为 f[n] | f[m-n-1] × f[n]
所以 gcd(f[n] , f[m]) = gcd(f[n] , f[m-n] × f[n+1]);
又因为 gcd(f[n] , f[n+1]) == 1;
证
gcd(f[n] , f[n+1]) = gcd(f[n] , f[n] + f[n-1]) = gcd(f[n] , f[n-1]) = gcd(f[n-2] , f[n-1]) = gcd(f[1] , f[2]) = 1;
所以 gcd(f[n] , f[m]) = gcd(f[n] , f[m-n]) = gcd(f[n] , f[m % n]);
交换一下 n,m
就可以看到这个很像求 n,m gcd的过程.
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int mod = 1e8;
inline int read()
{
register int x = 0 , f = 0; register char c = getchar();
while(c < '0' || c > '9') f |= c == '-' , c = getchar();
while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
return f ? -x : x;
}
int n , m;
struct Matrix
{
int a[2][2];
Matrix() { memset(a , 0 , sizeof a); }
Matrix friend operator * (const Matrix &A , const Matrix &B)
{
Matrix C;
for(int i = 0 ; i < 2 ; ++i) for(int j = 0 ; j < 2 ; ++j) for(int k = 0 ; k < 2 ; ++k) C.a[i][j] = (C.a[i][j] + (long long)A.a[i][k] * B.a[k][j] % mod) % mod;
return C;
}
}A , B , Ans;
int main()
{
n = read(); m = read(); int k = __gcd(n , m);
A.a[0][0] = A.a[1][0] = A.a[0][1] = 1;
B.a[0][0] = 1; Ans.a[0][0] = Ans.a[1][1] = 1; k--;
for( ; k ; k >>= 1 , A = A * A) if(k & 1) Ans = Ans * A;
Ans = B * Ans;
cout << Ans.a[0][0] << '
';
return 0;
}