洛谷传送门
题目描述
对于Fibonacci数列: 1 , 1 , 2 , 3 , 5 , 8 , 13...... 1,1,2,3,5,8,13...... 1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第 n n n项和第 m m m项的最大公约数是多少?
Update:加入了一组数据。
输入输出格式
输入格式:
两个正整数 n n n和 m m m。( n , m ≤ 1 0 9 n,m\le 10^9 n,m≤109)
注意:数据很大
输出格式:
F n 和 F m F_n和F_m Fn和Fm的最大公约数。
由于看了大数字就头晕,所以只要输出最后的 8 8 8位数字就可以了。
输入输出样例
输入样例#1:
4 7
输出样例#1:
1
说明
用递归&递推会超时
用通项公式也会超时
解题分析
做完这道题某数竞大佬才告诉我这是个常用结论qwq…
设不妨
m
>
n
m>n
m>n,
F
[
n
]
=
a
,
F
[
n
+
1
]
=
b
F[n]=a,F[n+1]=b
F[n]=a,F[n+1]=b, 那么
F
[
m
]
=
F
[
m
−
n
−
1
]
×
a
+
F
[
m
−
n
]
×
b
=
F
[
m
−
n
−
1
]
×
F
[
n
]
+
F
[
m
−
n
]
×
F
[
n
+
1
]
F[m]=F[m-n-1]\times a+F[m-n]\times b \\ =F[m-n-1]\times F[n]+F[m-n]\times F[n+1]
F[m]=F[m−n−1]×a+F[m−n]×b=F[m−n−1]×F[n]+F[m−n]×F[n+1]
所以:
g
c
d
(
F
[
n
]
,
F
[
m
]
)
=
g
c
d
(
F
[
n
]
,
F
[
m
−
n
]
×
F
[
n
+
1
]
)
gcd(F[n],F[m])=gcd(F[n],F[m-n]\times F[n+1])
gcd(F[n],F[m])=gcd(F[n],F[m−n]×F[n+1])
又因为
g
c
d
(
F
[
n
]
,
F
[
n
+
1
]
)
=
g
c
d
(
F
[
n
]
,
F
[
n
]
+
F
[
n
−
1
]
)
=
g
c
d
(
F
[
n
−
1
]
,
F
[
n
]
)
=
.
.
.
=
1
gcd(F[n],F[n+1]) \\=gcd(F[n],F[n] + F[n-1]) \\= gcd(F[n-1],F[n]) \\=... \\=1
gcd(F[n],F[n+1])=gcd(F[n],F[n]+F[n−1])=gcd(F[n−1],F[n])=...=1
所以
g
c
d
(
F
[
n
]
,
F
[
m
]
)
=
g
c
d
(
F
[
n
]
,
F
[
m
−
n
]
)
gcd(F[n],F[m])=gcd(F[n],F[m-n])
gcd(F[n],F[m])=gcd(F[n],F[m−n])
如此递归下去即可得
g
c
d
(
F
[
n
]
,
F
[
m
]
)
=
F
[
g
c
d
(
n
,
m
)
]
gcd(F[n],F[m])=F[gcd(n,m)]
gcd(F[n],F[m])=F[gcd(n,m)]。
然后套个矩阵快速幂即可 A C AC AC。
代码如下:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MOD 100000000
#define ll long long
struct Matrix
{
ll mat[2][2];
void clear() {memset(mat, 0, sizeof(mat));}
void set_unit() {clear(); mat[0][0] = mat[1][1] = 1;}
};
IN Matrix operator * (const Matrix &x, const Matrix &y)
{
Matrix ret; ret.clear();
for (R int i = 0; i < 2; ++i)
for (R int j = 0; j < 2; ++j)
for (R int k = 0; k < 2; ++k)
ret.mat[i][j] += x.mat[i][k] * y.mat[k][j];
for (R int i = 0; i < 2; ++i)
for (R int j = 0; j < 2; ++j)
ret.mat[i][j] %= MOD;
return ret;
}
IN Matrix fpow (R int tim)
{
Matrix ret; ret.set_unit();
Matrix mul = (Matrix){0, 1, 1, 1};
W (tim)
{
if(tim & 1) ret = ret * mul;
mul = mul * mul, tim >>= 1;
}
return ret;
}
int main(void)
{
int n, m, temp;
scanf("%d%d", &n, &m);
temp = std::__gcd(n, m);
if(temp <= 2) return puts("1"), 0;
Matrix ini = (Matrix){1, 0, 1, 0};
Matrix res = fpow(temp - 2);
printf("%d", (res * ini).mat[1][0]);
}