D(HDU3306)

Another kind of Fibonacci

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


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
 

Author
wyb
 

Source
 

Recommend
wxl



这种题目,难就难在构造矩阵上面,如果能够成功的构造出矩阵,那么剩下的内容都好解决,如果没有构造出来,那么就一点思路都没有了,没有构造出来。。。还是看别人的解题过程吧。

矩阵连乘求解。

首先我们列一个式子 A(n)=x*A(n-1)+b*A(n-2);

则A(n)^2=x^2*A(n-1)^2+y^2*A(n-2)^2+2*x*y*A(n-1)*A(n-2);

也就是说S(n)=S(n-1)+A(n)^2=S(n-1)+x^2*A(n-1)^2+y^2*A(n-2)^2+2*x*y*A(n-1)*A(n-2);

我们从中取出不能直接求解的部分构成一个矩阵M={S(n-1),A(n-1)^2,A(n-2)^2,A(n-1)*A(n-2)}

然后由此可以看出有一个辅助矩阵D={1          0         0     0

                                                x^2      x^2     1     x

                                                y^2      y^2     0     0

                                                2*x*y   2*x*y  0     y}

第一列是S(n)与S(n-1)的转化方程

第二列是A(n)^2与A(n-1)^2的转化方程

第三列是为了将A(n-2)变为A(n-1)

第四列:

         x*A(n-1)^2+y*A(n-1)*A(n-2)=(x*A(n-1)+y*A(n-2))*A(n-1)=A(n)*A(n-1)

由此的我们可以很方便的从S(n-1)求解出S(n),只需要一个辅助矩阵

然后为了提高效率,可以采用二进制的思想(二进制思想具体参见北大程序设计引导及在线实践的P169)

本题要对最终结果模10007,所以为了防止溢出,我们可以在乘法后立即模10007,不会改变数值(模定理具体参见白书180)



贴出我自己的代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>

using namespace std;

const int MOD = 10007;

long long int N, X, Y;

struct Matrix
{
	int date[4][4];
	void setE()
	{
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				date[i][j] = (i == j);
			}
		}
	}
	void setO()
	{
		memset(date, 0, sizeof(date));
	}
	
	void print()
	{
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				printf("%d ", date[i][j]);
			}
			cout << endl;
		}
	}
		
};

Matrix add(Matrix &a, Matrix &b)
{
	Matrix e;
	e.setO();
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			e.date[i][j] = (a.date[i][j] + b.date[i][j]) % MOD;
		}
	}
	return e;
}

Matrix mul(Matrix &a, Matrix &b)
{
	Matrix e;
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			e.date[i][j] = 0;
			for (int k = 0; k < 4; k++)
			{
				e.date[i][j] += a.date[i][k] * b.date[k][j] % MOD;
			}
			e.date[i][j] %= MOD;
		}
	}
	return e;
}

Matrix quick_pow(Matrix mat, long long int n)
{
	Matrix ans;
	ans.setE();
	while (n)
	{
		if (n & 1)
		{
			ans = mul(ans, mat);
		}
		mat = mul(mat, mat);
		n >>= 1;
	}
	return ans;
}



Matrix init()
{
	Matrix mat;
	mat.date[0][0] = 1;
	mat.date[0][1] = 0;
	mat.date[0][2] = 0;
	mat.date[0][3] = 0;
	mat.date[1][0] = mat.date[1][1] = (X % MOD) * (X % MOD) % MOD;
	mat.date[1][2] = 1;
	mat.date[1][3] = X % MOD;
	mat.date[2][0] = mat.date[2][1] = (Y % MOD) * (Y % MOD) % MOD;
	mat.date[2][2] = 0;
	mat.date[2][3] = 0;
	mat.date[3][0] = mat.date[3][1] = 2 * (X % MOD) * (Y % MOD) % MOD;
	mat.date[3][2] = 0;
	mat.date[3][3] = Y % MOD;
	return mat;
}
			
	


int main()
{
	int T[4] = {2, 1, 1, 1};
	while (scanf("%lld%lld%lld", &N, &X, &Y) != EOF)
	{
		Matrix A = init();
//		A.print();
		Matrix B = quick_pow(A, N - 1);
//		B.print();
		int ans = 0;
		for (int i = 0; i < 4; i++)
		{
			ans += T[i] * B.date[i][0] % MOD;
		}
		printf("%d\n", ans % MOD);
	}
//	system("pause");
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值