辗转相除
【题目描述】
现定义一个函数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时需要特判一下。 做题还是要大胆地猜想,大胆地下笔。 */