【矩阵快速幂专题】HDU 5950 Recursive sequence

http://acm.hdu.edu.cn/showproblem.php?pid=5950

Recursive sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3382    Accepted Submission(s): 1490

Problem Description

Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers a and b on a blackboard. And then, the cows would say their identity number one by one. The first cow says the first number a and the second says the second number b. After that, the i-th cow says the sum of twice the (i-2)-th number, the (i-1)-th number, and i4. Now, you need to write a program to calculate the number of the N-th cow in order to check if John’s cows can make it right. 

Input

The first line of input contains an integer t, the number of test cases. t test cases follow.
Each case contains only one line with three numbers N, a and b where N,a,b < 231 as described above.

Output

For each test case, output the number of the N-th cow. This number might be very large, so you need to output it modulo 2147493647.

Sample Input

2
3 1 2
4 1 10

Sample Output

85
369

Hint

In the first case, the third number is 85 = 2*1十2十3^4. In the second case, the third number is 93 = 2*1十1*10十3^4 and the fourth number is 369 = 2 * 10 十 93 十 4^4.

Source

2016ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)

 思路

题目大意:有一个递推公式f(i) = 2*f(i-2)+f(i-1)+i^4,f(1) = a,f(2) = b

现在给出a,b,和n,求f(n),a,b,n < 2^31

题目思路:矩阵快速幂,主要在于构造矩阵
原矩阵:

\begin{Bmatrix} b & a & 16 & 8 & 4 & 2 & 1 \end{Bmatrix}

递推矩阵:

\begin{Bmatrix} 1 & 1 & 0 & 0 & 0 & 0 & 0 \\ 2 & 0 & 0 & 0 & 0 & 0 & 0 \\ 1 & 0 & 1 & 0 & 0 & 0 & 0\\4 & 0 & 4 & 1 & 0 & 0 & 0\\6 & 0 & 6 & 3 & 1 & 0 & 0\\4 & 0 & 4 & 3 & 2 & 1 & 0\\1 & 0 & 1 & 1 & 1 & 1 & 1 \end{Bmatrix}

实际上就是用 
\begin{Bmatrix} f(i) & f(i-1) & i^4 & i^3 & i^2 & i & 1 \end{Bmatrix}
去推出 
{f(i+1)f(i)(i+1)4(i+1)3(i+1)2(i+1)1}

我的推导如下:

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll nmax=7;
const ll MOD=2147493647;
#define mod(x) ((x)%MOD)
 
int n;
struct mat{
	ll m[nmax][nmax];
}unit;
 
//A*B^(n-2)=C //C矩阵的首项即为f(n) 
mat operator *(mat a,mat b){
	mat ret;
	ll x;
	for(ll i=0;i<nmax;i++){//7*7
		for(int j=0;j<nmax;j++){
			x=0;
			for(ll k=0;k<nmax;k++){
				x+=mod((ll)a.m[i][k]*b.m[k][j]);
			}
			ret.m[i][j]=mod(x);
		}
	}
	return ret;
}
 
void init_unit(){
	for(ll i=0;i<nmax;i++){
		unit.m[i][i]=1;
	} 
	return;
}
mat pow_mat(mat a,ll n){//求矩阵a的n次幂 
	mat ret=unit;
	while(n){
		if(n&1) ret=ret*a;
		a=a*a;
		n>>=1;
	} 
	return ret;
}
int main(int argc, char** argv) {
	ll t;
	ll n,A,B; 
	init_unit();
	scanf("%lld",&t);
	while(t--){//需要求矩阵B的n-2次幂 
		scanf("%lld %lld %lld",&n,&A,&B);
		if(n==1) printf("%d\n",A);
		else if(n==2) printf("%d\n",B);
		else{
			mat a,b;
  			b.m[0][0] = 1,b.m[0][1] = 1,b.m[0][2] = 0,b.m[0][3] = 0,b.m[0][4] = 0,b.m[0][5] = 0,b.m[0][6] = 0;
            b.m[1][0] = 2,b.m[1][1] = 0,b.m[1][2] = 0,b.m[1][3] = 0,b.m[1][4] = 0,b.m[1][5] = 0,b.m[1][6] = 0;
            b.m[2][0] = 1,b.m[2][1] = 0,b.m[2][2] = 1,b.m[2][3] = 0,b.m[2][4] = 0,b.m[2][5] = 0,b.m[2][6] = 0;
            b.m[3][0] = 4,b.m[3][1] = 0,b.m[3][2] = 4,b.m[3][3] = 1,b.m[3][4] = 0,b.m[3][5] = 0,b.m[3][6] = 0;
            b.m[4][0] = 6,b.m[4][1] = 0,b.m[4][2] = 6,b.m[4][3] = 3,b.m[4][4] = 1,b.m[4][5] = 0,b.m[4][6] = 0;
            b.m[5][0] = 4,b.m[5][1] = 0,b.m[5][2] = 4,b.m[5][3] = 3,b.m[5][4] = 2,b.m[5][5] = 1,b.m[5][6] = 0;
            b.m[6][0] = 1,b.m[6][1] = 0,b.m[6][2] = 1,b.m[6][3] = 1,b.m[6][4] = 1,b.m[6][5] = 1,b.m[6][6] = 1;

            a.m[0][0] = B,a.m[0][1] = A,a.m[0][2] = 16,a.m[0][3] = 8,a.m[0][4] = 4,a.m[0][5] = 2,a.m[0][6] = 1;    
			b=pow_mat(b,n-2);
			a=a*b;
			//printf("%lld\n",mod(a.m[0][0]));
			printf("%lld\n",a.m[0][0]%MOD);
		} 
	}
	return 0;
}

参考链接:根据递推公式构造系数矩阵用于快速幂

                   https://blog.csdn.net/spring371327/article/details/52973534

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值