辗转相除的层数—变量出了问题

思路:

  a+b尽量小 ,极限情况就是b=a+x.

  同理 a=x+z. 

  于是z+x=a, x+a=b,..a+b=c,b+c=d.......像是一个广义斐波那契数列。

  F(a,b)=1,中 a+b最小的 是(1,1)。

  所以,是个标准的斐波那契数列。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MOD 1000000007
using namespace std;
struct node{
    int  v[2][2]; //注意最好开 long log 
}ans,f,ans1;
long long k;
node ch(node a,node b)
{
    
    for(int i=0;i<=1;i++)
    for(int j=0;j<=1;j++)
    {
        ans1.v[i][j]=0;
        for(int kk=0;kk<=1;kk++)
            ans1.v[i][j] = ( 1LL*ans1.v[i][j]+(1LL*a.v[i][kk]*b.v[kk][j])%MOD +MOD)%MOD;    //   没提前转化成(long long )再 取模,溢出后再取模就错了   
    }
    return ans1;
}
void fastlow()
{
    while(k)
    {
        if(k%2)    ans=ch(ans,f);
        k/=2; f=ch(f,f);
    }
}
int main()
{
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);    
    cin>>k;
    if(k==1)
    {
        printf("1 1");
        return 0;
    } 
    ans.v[0][0]=1;ans.v[0][1]=1;ans.v[1][0]=ans.v[1][1]=0;
    f.v[0][0]=1,f.v[0][1]=1,f.v[1][0]=1;f.v[1][1]=0;
    fastlow();
    printf("%d %d\n",(ans.v[0][1]+MOD)%MOD,(ans.v[0][0]+MOD)%MOD);    
    return 0;
}

 

posted @ 2017-09-20 17:47  浪矢-CL  阅读(120)  评论(0编辑  收藏  举报