zoukankan      html  css  js  c++  java
  • P3986 斐波那契数列

    题目描述

    定义一个数列:

    f(0)=a,f(1)=b,f(n)=f(n−1)+f(n−2)

    其中 a,b均为正整数,n≥2

    问有多少种 (a,b),使得 k 出现在这个数列里,且不是前两项。

    由于答案可能很大,你只需要输出答案模 10^9 + 7 的结果即可。

    输入输出格式

    输入格式:

    一行一个整数 k

    输出格式:

    一行一个数,表示答案模10^9 + 7的结果。

    输入输出样例

    输入样例#1: 
    19260817
    输出样例#1: 
    34166325
    输入样例#2: 
    1000000000
    输出样例#2: 
    773877569

    说明

    1≤k≤109

    Solution:

      一道趣味数学题,想了有快40多分钟。。。

      本题可以枚举系数用扩展欧几里德求解通解,然后求正整数解个数,显然当某次无整数解时,再往后也不会再有正整数解了(很简单的道理,等下我的方法里有解释)。

      讲讲我的算法,个人认为上述的方法简单些,但是我想到一个很特殊的斐波拉契的性质 F[i]*F[i+3]-F[i+1]*F[i+2]=(-1)i-1 于是入坑用了一个稍微复杂但绝对好理解的算法。

      然后今天月考炸完,在机房无聊在白板上写本题详细思路(为写博做准备),结果发现本题要用我的方法写的话实在是长。

      这是我在黑板上写的:

      肯定不够清晰,所以还是解释一波:

      题意是给定一个k,问有多少个f[1]=a,f[2]=b,使得k出现在该斐波拉契数列中。

      等价于求解 a+b=k、a+2b=k、2a+3b=k、3a+5b=k…的以相邻两项斐波拉契数为系数的不定方程的正整数解的个数。

      因为题目中说道a、b≥1,所以当斐波拉契数的某相邻两项f[i]+f[i+1]>k时便可不用在求不定方程了(显然无正整数解)。

      于是可以枚举相邻的两项斐波拉契数作系数,然后累加正整数解的个数。

       我们由裴蜀定理可知: $$ax+by=c quad a,b,cin Z*$$

      有整数解的充要条件是: $$gcd(a,b)|c$$

      证明:

      $ecause quad$ $a=pgcd(a,b),quad$ $b=qgcd(a,b)$

        $ herefore quad$ $ax+by=pgcd(a,b)x+qgcd(a,b)y=(px+qy)*gcd(a,b)=c$

      $ecause quad$ $(px+qy),gcd(a,b)in Z*$

      $ herefore quad$ $gcd(a,b)|c$

      

      不妨设$x,y$为 $ax+by=c$ 的一组解,则由解$x,y$可推出其它解为:

      $x1=x+frac{b}{gcd(a,b)}*t,quad$ $y2=x-frac{a}{gcd(a,b)}*tquad,tin Z*$

      证明:

      $ecause quad ax+by=c$

      $ herefore quad ax+by+frac{ab}{gcd(a,b)}*t-frac{ab}{gcd(a,b)}*t=c$

      $ herefore quad a(x+frac{b}{gcd(a,b)}*t)+b(y-frac{a}{gcd(a,b)}*t)=c$

      $ herefore quad$ $x1=x+frac{b}{gcd(a,b)}*t,quad$ $y2=x-frac{a}{gcd(a,b)}*tquad,tin Z*$

      

      然后我们以斐波拉契中的相邻两项f[i]和f[i+1]为系数

      不难发现$f[i]*f[i+3]-f[i+1]*f[i+2]=(-1)^{i-1}$

      证明:

      设$f[i]=a,f[i-1]=bquad$ 则$f[i+1]=a+b,f[i+2]=2a+b,f[i+3]=3a+2b$

      原式$=a*(3a+2b)-(a+b)*(2a+b)$

        $=a^2-b^2-ab$

        $=(a-b)(a+b)-ab$

        $=f[i-2]*f[i+1]-f[i-1]*f[i]$

      继续将新式子往下递归

      1、当$2|i$,必定递归到$f[0]*f[3]-f[1]*f[2]=-1$(注意到$f[0]$无意义,所以$f[0]=0$),所以i为偶数时$f[i]*f[i+3]-f[i+1]*f[i+2]=-1$

      2、否则,必定递归到$f[1]*f[4]-f[2]*f[3]=1$,所以i为奇数时$f[i]*f[i+3]-f[i+1]*f[i+2]=1$

      $ herefore quad$ $f[i]*f[i+3]-f[i+1]*f[i+2]=(-1)^{i-1}$

      有了上面这个性质,易得题目中的$f[i]x+f[i+1]y=k$必定有通解:

      $x=(-1)^{i-1}*k*f[i+3],quad$ $y=(-1)^{i}*k*f[i+2]$

      然后易得斐波拉契数列的相邻两项$f[i]$和$f[i+1]$互质,即$gcd(f[i],f[i+1])=1$,  

      证明(由欧几里德定理):

      $ecause quad$ $gcd(f[i],f[i+1])=gcd(f[i],f[i+1]-f[i])=gcd(f[i],f[i-1])…=gcd(f[1],f[2])=1$

      $ herefore quad$ $gcd(f[i],f[i+1])=1$

      于是由上述性质可知:

      $f[i]x+f[i+1]y=k$的整数解为$x1=(-1)^{i-1}*k*f[i+3]+f[i+1]*t,quad$ $y1=(-1)^{i}*k*f[i+2]-f[i]*t,quad tin Z*$

      显然由于$(-1)^{i-1},(-1)^{i}$中必定有一个为-1,于是$x$和$y$中有且仅有一负数。

      1、当$x<0$,先使x变为最小整数解。

        则xmin $=x+(frac{left| x ight|}{f[i+1]}+1)*f[i+1]$

        ymax $=y-(frac{|x|}{f[i+1]}+1)*f[i]$

        此时求其它正整数解时$x$单调递增,$y$单调递减。

        $ herefore quad$ 此时的正整数解的个数$=lceil frac{ymax}{f[i]} ceil$

      2、当$y<0$,和上面同理知此时的正整数解个数$=lceil frac{xmax}{f[i+1]} ceil$

      

      按照上述方法本题便能完美的解决。

      由于斐波拉契数最多到第90多项时就爆long long了,所以本题此方法复杂度O(n),n≤92。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    using namespace std;
    
    const ll mod=1e9+7;
    ll f[100],x,y,n,i,ans;
    int main()
    {
        cin>>n;
        f[1]=f[2]=1;ans=n-1;
        for(i=3;i<=100;i++){f[i]=f[i-1]+f[i-2];if(f[i]>=n)break;}
        //cout<<i<<endl;
        for(int j=2;j<=i;j++){
            int q=pow(-1,j-1);
            x=n*q*f[j+3],y=-n*q*f[j+2];
            if(x<0){y-=(abs(x)/f[j+1]+1)*f[j];if(y>0)ans=ans+ceil(1.0*y/f[j]);ans%=mod;}
            else if(y<0){x-=(abs(y)/f[j]+1)*f[j+1];if(x>0)ans=ans+ceil(1.0*x/f[j+1]);ans%=mod;}
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    模拟测试20190806
    替罪羊树学习日记
    [Usaco2015 Jan]Moovie Mooving
    [NOIP2016]愤怒的小鸟
    [BZOJ1556]墓地秘密
    [SDOI2009]学校食堂Dining
    [SCOI2008]奖励关
    [洛谷3930]SAC E#1
    [BZOJ2809/APIO2012]dispatching
    [Usaco2018 Open]Disruption
  • 原文地址:https://www.cnblogs.com/five20/p/8684357.html
Copyright © 2011-2022 走看看