杭电 3306 Another kind of Fibonacci 构造矩阵二分幂

       这道题题意是比较简单的,方法也很容易想,构建矩阵,主要难度在构建矩阵的地方。由于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 <= 2 31 – 1
X : 2<= X <= 2 31– 1
Y : 2<= Y <= 2 31 – 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;
}


你可能感兴趣的:(杭电 3306 Another kind of Fibonacci 构造矩阵二分幂)