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

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 <= 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
 
这是一个变形的科波菲尔数列问题,重点是自己构造一个矩阵
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)^2 A(n-2)^2 A(n-1)A(n-2) }; Matrix W= { s(n) A(n)^2 A(n-1)^2 A(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初始化为单位矩阵,人为输入origin
void 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值