zoukankan      html  css  js  c++  java
  • P1306 斐波那契公约数

    题目描述

    对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少?

    输入输出格式

    输入格式:

    两个正整数n和m。(n,m<=10^9)

    注意:数据很大

    输出格式:

    Fn和Fm的最大公约数。

    由于看了大数字就头晕,所以只要输出最后的8位数字就可以了。

    输入输出样例

    输入样例#1: 
    4 7
    输出样例#1: 
    1

    说明

    用递归&递推会超时

    用通项公式也会超时

    Solution:

      本题其实并不难,开始被题意吓到了,结果后面写出了式子都没看出来(手动滑稽~)。

      方法:结论+矩阵加速

      结论:$$gcd(F[n],F[m])=F[gcd(n,m)]$$

      证明:

      我们设$n<m$,$F[n]=a$和$F[n+1]=b$。

      则$F[n+2]=a+b,F[n+3]=a+2b,…F[m]=F[m-n-1]a+F[m-n]b$

      $ecause quad$ $F[n]=a,F[n+1]=b,F[m]=F[m-n-1]a+F[m-n]b$

      $ herefore quad$ $F[m]=F[m-n-1]*F[n]+F[m-n]*F[n+1]$

      又$ecause quad$ $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]$

      $ herefore quad 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+1]-F[n])$

                           $=gcd(F[n],F[n-1])$

                $=gcd(F[n-2],F[n-1])$

                $……$

                $=gcd(F[1],F[2])=1$

          $ herefore quad gcd(F[n],F[n+1])=1$

      由引理知:

      $F[n],F[n+1]$互质

      而 $gcd(F[n],F[m])=gcd(F[n],F[m-n]*F[n+1])$

      $ herefore quad$ $gcd(F[n],F[m])=gcd(F[n],F[m-n])$

      即$gcd(F[n],F[m])=gcd(F[n],F[m;mod;n])$

      继续递归,将$m1=m;mod;n$,则$gcd(F[n],F[m])=gcd(F[n;mod;m1],F[m1])$

      $…$

      不难发现,整个递归过程其实就是在求解$gcd(n,m)$

      最后递归到出现$F[0]$时,此时的$F[n]$就是所求gcd。 

      $$ herefore quad gcd(F[n],F[m])=F[gcd(n,m)]$$

      于是本题就转为求$gcd(n,m)$,然后求斐波拉契数列的$F[gcd(n,m)]$项后8位(即对100000000取模)。

      至于矩阵的构造:

      初始矩阵 egin{bmatrix} F[2]=1 & F[1]=1end{bmatrix} 以及中间矩阵 egin{bmatrix} 1 & 1 \ 1 & 0 end{bmatrix}

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define mem(p) memset(&p,0,sizeof(p))
    using namespace std;
    const ll mod=1e8;
    ll n,m;
    struct mat{ll a[3][3],r,c;};
    il mat mul(mat x,mat y)
    {
        mat p;
        mem(p);
        for(int i=0;i<x.r;i++)
            for(int j=0;j<y.c;j++)
                for(int k=0;k<x.c;k++)
        p.a[i][j]=(p.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
        p.r=x.r,p.c=y.c;
        return p;
    }
    il void fast(ll k)
    {
        mat p,ans;
        mem(p),mem(ans);
        p.r=p.c=2;
        p.a[0][0]=p.a[0][1]=p.a[1][0]=1;
        ans.r=1,ans.c=2;
        ans.a[0][0]=ans.a[0][1]=1;
        while(k)
        {
            if(k&1)ans=mul(ans,p);
            p=mul(p,p);
            k>>=1;
        }
        cout<<ans.a[0][0];
    }
    il ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    int main()
    {
        ios::sync_with_stdio(0);
        cin>>n>>m;
        n=gcd(n,m);
        if(n<=2)cout<<1;
        else fast(n-2);
        return 0;
    }
  • 相关阅读:
    Python入门11 —— 基本数据类型的操作
    Win10安装7 —— 系统的优化
    Win10安装6 —— 系统的激活
    Win10安装5 —— 系统安装步骤
    Win10安装4 —— 通过BIOS进入PE
    Win10安装2 —— 版本的选择与下载
    Win10安装1 —— 引言与目录
    Win10安装3 —— U盘启动工具安装
    虚拟机 —— VMware Workstation15安装教程
    Python入门10 —— for循环
  • 原文地址:https://www.cnblogs.com/five20/p/8708445.html
Copyright © 2011-2022 走看看