辗转相除

【题目描述】

现定义一个函数F(a,b),表示对于数对(a,b)调用辗转相除法的步数为多少。

已知F(a,b)=k,求(a,b)使得a+b尽量小,答案模109+7。

【输入描述】

输入一个整数,表示k。

【输出描述】

输出两个整数,表示a、b(a < b)。

【输入样例】

1000000007

【输出样例】

0 1000000006

【数据范围及提示】

对于10%的数据,k < 10;

对于40%的数据,k < 50;

对于60%的数据,k < 108

对于90%的数据,k < 1010

对于100%的数据,k < 1015

源代码:

#include<cstdio>
#define INF 1000000007
long long K,i[2][2],f[2][2];
void Multi(long long t1[2][2],long long t2[2][2]) //C++中,数组为全局变量。
{
    long long t3[2][2];
    t3[0][0]=t3[0][1]=t3[1][0]=t3[1][1]=0;
    for (int a=0;a<2;a++) //横行。
      for (int b=0;b<2;b++) //纵列。
        for (int c=0;c<2;c++) //序号。
          t3[a][b]=(t3[a][b]+t1[a][c]*t2[c][b]%INF)%INF;
    for (int a=0;a<2;a++) //2*2的答案与1*2的答案是等效的。
      for (int b=0;b<2;b++)
        t1[a][b]=t3[a][b];
}
int main()
{
    scanf("%lld",&K);
    if (K==0) //特判一下。
    {
        printf("0 1");
        return 0;
    }
    if (K==1)
    {
        printf("1 1");
        return 0;
    }
    i[0][0]=i[0][1]=i[1][0]=1;
    f[0][0]=3;
    f[0][1]=2;
    K-=2;
    while (K) //矩阵乘法快速幂求Fibonacci数列。
    {
        if (K&1)
          Multi(f,i);
        K>>=1;
        Multi(i,i);
    }
    printf("%I64d %I64d",f[0][1],f[0][0]); //%lld和%I64d要分清!
    return 0;
}

/*
    挺有意思的一道题:
        推一推会发现:
            (0,1)--(1,1)--(2,3)--(3,5)--(5,8)--(8,13)--······
        类似于Fibonacci数列,只是当K=1时需要特判一下。
    做题还是要大胆地猜想,大胆地下笔。
*/
原文地址:https://www.cnblogs.com/Ackermann/p/5933885.html