hdu4549

来源:互联网 发布:nginx websocket 配置 编辑:程序博客网 时间:2024/06/06 10:33

题意难得的中文字啊。。

Problem Description
M斐波那契数列F[n]是一种整数数列,它的定义如下:

F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )

现在给出a, b, n,你能求出F[n]的值吗?
 

Input
输入包含多组测试数据;
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
 

Output
对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。
 

Sample Input
0 1 06 10 2
 

Sample Output

0
60

先来补一下基础知识吧,关于

斐波那契数列

数列的递推公式为:f(1)=1,f(2)=2,f(n)=f(n-1)+f(n-2)(n>=3)

   用矩阵表示为:

进一步推导:


也可以直接


然后这道题的指数是满足该数组的,利用矩阵快速幂得到系数,然后在相乘,因为n很大,矩阵乘法中可能益处,这里要用到指数循环节
当A、M互质时 A^X = A^( X mod Eular(M) ) ( mod M ) .M=1000000007 ,Eular(M)=1000000006 ;
所以矩阵乘法中模1000000006

相乘的时候同样利用快速幂降低复杂度

//应该是用矩阵快速幂才可以的  //二分快速幂 + 费马小定理 +指数循环节 //模数之所以为1000000006是因为根据指数循环节可得 当A、M互质时 A^X = A^( X mod Eular(M) ) ( mod M ) .费马小定理 A^euler(M) = 1 (mod M),其中M为素数。 #include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<vector> using namespace std;#define inf 1000000007void  f(int a,int b,int n){int i,j,k;long long A[2][2]={1,1,1,0};long long res[2][2]={1,0,0,1};long long tmp[2][2];while(n){if(n&1){for(i=0;i<2;i++){for(j=0;j<2;j++){tmp[i][j]=res[i][j];}}res[0][0]=res[0][1]=res[1][0]=res[1][1]=0;for(i=0;i<2;i++){for(j=0;j<2;j++){for(k=0;k<2;k++)res[i][j]=(res[i][j]+tmp[i][k]*A[k][j])%(inf-1);}}}for(i=0;i<2;i++){for(j=0;j<2;j++)tmp[i][j]=A[i][j];}A[0][0]=A[0][1]=A[1][0]=A[1][1]=0;for(i=0;i<2;i++){for(j=0;j<2;j++){for(k=0;k<2;k++)A[i][j]=(A[i][j]+tmp[i][k]*tmp[k][j])%(inf-1);}}n>>=1;}long long ans=1;int cnt=res[0][1];long long aa=(long long)a,bb=(long long)b;while(cnt){if(cnt&1)    {    ans*=bb;    ans%=inf;    } bb=bb*bb;bb%=inf;cnt>>=1;}cnt=res[1][1];while(cnt){if(cnt&1){ans*=aa;ans%=inf;}aa=aa*aa;aa%=inf; //这里忘记取余了 结果WA。。。。~~~~(>_<)~~~~  cnt>>=1;}cout<<ans<<endl;}int main(){    int a,b,n;while(scanf("%d%d%d",&a,&b,&n)==3){if(n==0){cout<<a<<endl;continue;} else if(n==1){cout<<b<<endl;continue;}else f(a,b,n);}}




0 0