Luo Gu P1306 Fibonacci Convention (number theory + proof)

Topic Link

Title effect: to give you a n, m (1 <= n, m <= 1e9), seeking __gcd (F [n], F [m])% 1e8.

First of all I am here to propose a theorem of number theory: __ gcd (F [n], F [m]) = F [__ gcd (n, m)].

 

Knowing this fact, this problem in number theory Theorem becomes very easy, simply requires the greatest common divisor of n, m, and acceleration demand using matrix F [__ gcd (n, m)] of the modulo to 1e8.

But why the theorem is correct?


 

Certify as follows:

Provided n <m, and F. [N-] = A, F. [N-+. 1] = B

     F[n+2]=a+b

     F[n+3]=a+2*b=F[n]+2*F[n+1]

     F[n+4]=2*a+3*b=2*F[n]+3*F[n+1]

     F[n+5]=3*a+5*b=3*F[n]+5*F[n+1]

     ...

Difficult to find F [n + x] = F [x-1] * F [n] + F [x] * F [n + 1]

     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]);

Since  F [mn-1] * F [n]% F [n] == 0

Therefore __gcd ( F. [N-], F. [M]) = __ GCD ( F. [N-], F. [Mn] F. * [N-+. 1]);

 

Proof road seems stuck here, because this formula is difficult to go simplification, while the single from this equation is difficult to see anything, then we need another lemma: __ gcd (F [n] , F [n + 1]) = 1;

Proof of Lemma is relatively simple:

  __gcd(F[n],F[n+1])=__gcd(F[n],F[n]+F[n-1])

             =__gcd(F[n],F[n-1])

             =__gcd(F[n-1]+F[n-2],F[n-1])

             =__gcd(F[n-2],F[n-1])

             ......

             =__gcd(F[1],F[2])=1

We draw __gcd (F [n], F [n + 1]) = 1 after the can continue __gcd ( F. [N-], F. [M]) = __gcd ( F. [N-], F. [Mn] * F [n + 1]) for simplification

Finally __gcd ( F. [N-], F. [M]) = __gcd ( F. [N-], F. [Mn])

             =__gcd(F[n],F[m%n])

             ......

             =F[__gcd(n,m)]

Thus, proof of completion ~

 


 

The following code is placed on this topic AC

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int,int> PII;
const int MAXN = 1e6+10;
const double EPS = 1e-12;
const ll mod = 1e8;

ll n,mm;
struct Mat{
    ll m[5][5];
    Mat(){
        memset(m,0,sizeof(m));
    }
    inline void build(){
        for(int i=1;i<=2;i++)m[i][i]=1;
    }
}a;

Food Mul (Food x, Food y) {
    Mat c;
    for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
                c.m[j][i]=(c.m[j][i]+x.m[j][k]*y.m[k][i]%mod)%mod;
    return c;
}

Mat poww(Mat x,ll y){
    Mat aa;aa.build();
    while(y){
        if(y&1)aa=Mul(aa,x);
        x=Mul(x,x);
        y>>=1;
    }
    return aa;
}

int main ()
{
    scanf("%lld %lld",&n,&mm);
    ll p=__gcd(n,mm);
    a.m[1][1]=a.m[2][1]=a.m[1][2]=1;
    With ans = poww (a, p 1 );
    printf("%lld",ans.m[1][1]);
}

Guess you like

Origin www.cnblogs.com/Mmasker/p/12059911.html