HDU3306(科波菲尔数列+快速幂)

来源:互联网 发布:免签约php发卡平台 编辑:程序博客网 时间:2024/05/19 10:41

Another kind of Fibonacci

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1200    Accepted Submission(s): 454


Problem Description
As we all known , the Fibonacci series : F(0) = 1, F(1) = 1, F(N) = F(N - 1) + F(N - 2) (N >= 2).Now we define another kind of Fibonacci : A(0) = 1 , A(1) = 1 , A(N) = X * A(N - 1) + Y * A(N - 2) (N >= 2).And we want to Calculate S(N) , S(N) = A(0)2 +A(1)2+……+A(n)2.

 

Input
There are several test cases.
Each test case will contain three integers , N, X , Y .
N : 2<= N <= 231 – 1
X : 2<= X <= 231– 1
Y : 2<= Y <= 231 – 1
 

Output
For each test case , output the answer of S(n).If the answer is too big , divide it by 10007 and give me the reminder.
 

Sample Input
2 1 1 3 2 3
 

Sample Output
6196
 
这是一个变形的科波菲尔数列问题,重点是自己构造一个矩阵
Matrix P ={1,1,0,0,0,x^2,y^2,2xy,0,1,0,0,0,x,0,y};
Matrix Q={s(n-1)A(n-1)^2A(n-2)^2A(n-1)A(n-2)};Matrix W={s(n)A(n)^2A(n-1)^2A(n)A(n-1)};
自然P*Q=W
#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream> using namespace std;//N表示矩阵的N次幂int N;int nn,xx,yy;const int mod= 10007 ;//此处假设矩阵为3*3阶//origin存放需计算的矩阵,res存放答案矩阵struct matrix{int a[4][4];}origin,res;//直接将2个矩阵相乘x*y,返回计算后的矩阵matrix multiply(matrix x,matrix y){matrix temp;memset(temp.a,0,sizeof(temp.a));for(int i=0;i<4;i++){for(int j=0;j<4;j++){for(int k=0;k<4;k++){temp.a[i][j]=(temp.a[i][j]+x.a[i][k]*y.a[k][j])%mod;}}}return temp;}//将res初始化为单位矩阵,人为输入originvoid init(){memset(origin.a,0,sizeof(origin));xx=xx%mod;yy=yy%mod;origin.a[0][0]=origin.a[0][1]=1;origin.a[1][1]=(xx*xx)%mod;origin.a[1][2]=(yy*yy)%mod;origin.a[1][3]=(2*xx*yy)%mod;origin.a[2][1]=1;origin.a[3][1]=xx;origin.a[3][3]=yy;//将res.a初始化为单位矩阵 memset(res.a,0,sizeof(res.a));res.a[0][0]=res.a[1][1]=res.a[2][2]=res.a[3][3]=1;                  }//矩阵快速幂的计算void calc(int n){while(n){if(n&1)res=multiply(res,origin);n>>=1;origin=multiply(origin,origin);}}int main(){    while(~scanf("%d%d%d",&nn,&xx,&yy))    {init();calc(nn);int ans=(res.a[0][0]%mod+res.a[0][1]%mod+res.a[0][2]%mod+res.a[0][3]%mod)%mod;printf("%d\n",ans);    }    return 0;}


原创粉丝点击