杭电 3306 Another kind of Fibonacci 构造矩阵二分幂
2012-03-23 17:19 javaspring 阅读(264) 评论(0) 收藏 举报这道题题意是比较简单的,方法也很容易想,构建矩阵,主要难度在构建矩阵的地方。由于A(n)=x*A(n-1)+Y*(n-2),因此可以把A(n)平方,再由S(n)=S(n-1)+A(n)*A(n),所以可以构建矩阵{A(n-2)*A(n-2),A(n-1)*A(n-1),A(n-1)*A(n-2),S(n-1)},{A(n-1)*A(n-1),A(n)*A(n),A(n-1)*A(n),S(n)},构建出矩阵之后就很容易了。。题目:
Another kind of Fibonacci
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 720 Accepted Submission(s): 296
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
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
6 196
ac代码:
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long ll;
const ll MAX=10007;
const int row=5;//矩阵的维数,根据题目要求改变
ll aa[11][11],bb[11][11];//aa,bb存储矩阵
ll cc[11][11];//结果矩阵
ll dd[11][11];//单位矩阵
ll mi,x,y;//多少次方
class matrix{
public:
void input(ll f[11],ll num[11]);
void initmatrix(ll p[11],ll q[11]);
void matrixmi(int x);//矩阵幂
void matrixfun(ll a[11][11],ll b[11][11]);//矩阵乘积
};
//构造矩阵
void matrix::initmatrix(ll ff[11],ll a[11]){
memset(aa,0,sizeof(aa));
memset(bb,0,sizeof(bb));
for(int i=1;i<=row;++i){
for(int j=1;j<=row;++j)
dd[i][j]=0;
dd[i][i]=1;
}
for(int i=1;i<row;++i)
aa[1][i]=ff[i];
aa[1][row]=a[row];//原矩阵
bb[2][1]=1;bb[1][2]=a[1];bb[2][2]=a[2];bb[3][2]=a[3];
bb[2][3]=x;bb[3][3]=y;bb[1][4]=y*y;bb[2][4]=x*x;
bb[3][4]=2*x*y;bb[4][4]=1;
}
//矩阵乘法
void matrix::matrixfun(ll a[11][11],ll b[11][11]){
long long sum=0;
memset(cc,0,sizeof(cc));
for(int i=1;i<=row;++i){
for(int j=1;j<=row;++j){
sum=0;
for(int k=1;k<=row;++k)
{ sum+=(a[i][k]*b[k][j]);}
cc[i][j]=(sum%MAX);
}
}
}
//矩阵二分幂
void matrix::matrixmi(int x){
while(x){
if(x&1){
matrixfun(dd,bb);
for(int i=1;i<=row;++i)
for(int j=1;j<=row;++j)
dd[i][j]=cc[i][j];
}
matrixfun(bb,bb);
for(int i=1;i<=row;++i)
for(int j=1;j<=row;++j)
bb[i][j]=cc[i][j];
x=x>>1;
}
matrixfun(aa,dd);
}
int main(){
while(~scanf("%lld%lld%lld",&mi,&x,&y)){
x=x%MAX;y=y%MAX;
ll f[11],num[11];
f[1]=1;f[2]=1;f[3]=1;f[4]=2;
num[1]=y*y;num[2]=x*x;num[3]=2*x*y;num[4]=0;num[5]=0;
matrix mm;
if(mi==1){
cc[1][row-1]=2%MAX;
}
else if(mi==0)
cc[1][row-1]=1%MAX;
else{
mm.initmatrix(f,num);
mm.matrixmi(mi-1);
}
printf("%lld\n",cc[1][row-1]);
}
return 0;
}
浙公网安备 33010602011771号