第四篇:P1306
题解补完计划:第五篇
显然,猜想 \((F_n,F_m) = F_{(n,m)}\),接下来是证明。
引理1: \((F_n,F_{n-1}) = 1\)
因为,\(F_n - F_{n-1} = F_{n-2}\),所以 \((F_n, F_{n-1}) = (F_{n-1}, F{n-2})\),根据辗转相除法(相减),可知 \((F_n, F_{n-1}) = (F_1, F_0) = 1\),故,得证。
引理2: \(F_{n+m} = F_{n-1}F_m+F_nF_{m+1}\)
我们固定 \(n\), 尝试对 \(m\) 进行归纳。
-
\(m \le 1\)
显然成立 -
\(2\le m\)
我们令对于 \(m, m-1\) 都成立,则有:
\(\begin{aligned} F_{n+m+1} &= F_{n+m} + F_{n+m-1} \\ &= F_{n-1}F_m+F_nF_{m+1}+F_{n-1}F_{m-1}+F_nF_m \\ &= F_{n-1}(F_m+F_{m-1}) + F_n(F_m+F_{m+1}) \\ &= F_{n-1}F_{m+1} + F_nF_{m+1} \end{aligned}\)证毕。
结论 \((F_n,F_m) = F_{(n,m)}\)
由 引理2 可知
\(\begin{aligned}
(F_n, F_m) &= (F_n,F_{n+(m-n)}) \\
&= (F_n, F_{n-1}F_{m-n}+F_nF_{m-n+1})\\
&= (F_n, F_{n-1}F_{m-n})
\end{aligned}\)
由 引理1,所以 \((F_n, F_m) = (F_n, F_{m-n})\)。 根据辗转相除法(相减),所以 \((F_n,F_m) = F_{(n,m)}\) 证毕。
好我们在知道 \((F_n, F_m) = F_{(n,m)}\),那是不是就可以只求一个 \(F_{(n,m)}\) 的值,递推做完了,但是 \((n,m)\) 可能到达 \(10^9\) 会超时,我们考虑矩阵优化。
因为 \(F_{n+1} = F_n + F_{n-1}\), 所以我们可以写出下面这个转移矩阵。
\(\begin{bmatrix}
1 & 1 \\ 1 & 0
\end{bmatrix}\)
\(\begin{bmatrix}
F_n \\ F_{n-1}
\end{bmatrix}\)
$ = \(
\)\begin{bmatrix}
F_{n+1} \ F_n
\end{bmatrix}$
我们发现它是对一个重复的矩阵进行转移,所以我们可以用矩阵快速幂优化。
代码:
#include<bits/stdc++.h>
using namespace std;
#define mod 100000000
#define intl long long
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
intl x=0,k=1;char ch=getchar();
while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*k;
}
void write(intl x) {
if(x > 9) write(x/10);
putchar(x%10+'0');
}
struct matx{
intl a[5][5];
matx operator * (const matx&b) const {
matx ans;memset(ans.a,0,sizeof ans.a);
For(k,1,2) For(i,1,2) For(j,1,2)
ans.a[i][j] = (ans.a[i][j]+a[i][k]*b.a[k][j])%mod;
return ans;
}
}mat;
matx matpow(matx a,intl b){
matx ans;
ans.a[1][1]=ans.a[2][1]=1;
ans.a[1][2]=ans.a[2][2]=0;
a.a[1][1]=a.a[1][2]=a.a[2][1]=1;
while(b) {
if(b&1) ans=a*ans;
a=a*a;b>>=1;
}
return ans;
}
int main(){
intl n=read(),m=read();
n=__gcd(n,m);
if(n <= 2) puts("1");
else {
matx ans=matpow(mat,n-2);
printf("%lld",ans.a[1][1]);
}
return 0;
}

浙公网安备 33010602011771号