51nod1306斐波那契公约数(数论推公式,矩阵快速幂优化递推序列)

题目链接:https://www.luogu.org/problemnew/show/P1306

题意很清晰,数论推公式题。(推出来你就做出来了。推导过程我就不说了(其实我也不会逃))

1.gcd(f(n),f(m))=f(gcd(n,m))。(知道这个,下面就是矩阵快速幂水题了,求斐波那契第x项)

2.矩阵快速幂求斐波那契第x项

需要注意的是!先取余保留最后8位再计算公约数的话值就变了不对的。你先找出这个值在取余保留最后8位的话才对。(不信自己样例模拟一下就知道这是多么的错,然而还容易往这想)

 1 #include <iostream>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod=1e8;
 5 const int maxn=3;
 6 ll n,m,x;
 7 struct jz//矩阵部分
 8 {
 9     ll a[maxn][maxn];
10 }base,unit;
11 jz operator*(jz aa,jz bb)
12 {
13     jz c;
14     for(ll i=1;i<=maxn-1;i++)
15     {
16         for(ll j=1;j<=maxn-1;j++)
17         {
18             ll t=0;
19             for(ll k=1;k<=maxn-1;k++) t=(t%mod+aa.a[i][k]%mod*bb.a[k][j]%mod)%mod;
20             c.a[i][j]=t%mod;
21         }
22     }
23 
24     return c;
25 }
26 
27 void Init()//初始化
28 {
29     for(int i=1;i<=maxn-1;i++) unit.a[i][i]=i;//单位矩阵
30 
31     base.a[1][1]=1; base.a[1][2]=1;//底数矩阵
32     base.a[2][1]=1; base.a[2][2]=0;
33 }
34 
35 ll gcd(ll a,ll b)//最大gcd
36 {
37     return b?gcd(b,a%b):a;
38 }
39 
40 jz Qpow(jz base,ll b)//快速幂
41 {
42     jz r=unit;
43     while(b)
44     {
45         if(b&1) r=r*base;
46         base=base*base;
47         b>>=1;
48     }
49 
50     return r;
51 }
52 
53 int main()
54 {
55     ios::sync_with_stdio(false); cin.tie(0);
56 
57     cin>>n>>m;
58 
59     x=gcd(n,m);
60     if(x==0) cout<<'0'<<endl;
61     else if(x==1) cout<<'1'<<endl;
62     else if(x==2) cout<<'1'<<endl;
63     else
64     {
65         Init();
66         jz ans=Qpow(base,x-2);
67         ll anss=(ans.a[1][1]*1+ans.a[1][2]*1)%mod;//注意取模,这里也会超....
68         cout<<anss<<endl;
69     }
70 
71     return 0;
72 }

完。

原文地址:https://www.cnblogs.com/redblackk/p/9968828.html