【矩阵快速幂】nth Term LightOJ – 1096

You have to find the nth term of the following function:

f(n) = a * f(n-1) + b * f(n-3) + c, if(n > 2)

     = 0, if(n ≤ 2)

Input
Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case contains four integers n (0 ≤ n ≤ 108), a b c (1 ≤ a, b, c ≤ 10000).

Output
For each case, print the case number and f(n) modulo 10007.

Sample Input
2

10 1 2 3

5 1 3 9

Sample Output
Case 1: 162

Case 2: 27

矩阵快速幂。就是快速幂的乘运算换成了矩阵乘运算。递推数列写成矩阵形式。

第一次交TLE了,下来吧输入改成scnaf,加了个n<=2的特判,就过了

a 0 b c        f[n-1]       f[n]
1 0 0 0        f[n-2[       f[n-1]
0 1 0 0        f[n-3]       f[n-2]
0 0 0 1           1             1

 

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
using namespace std;

struct mt{
	int mmt[10][10];
}ans,res;
int t,hn,ha,hb,hc;
mt mul(mt a,mt b,int n)
{
	mt tmp;
	memset(tmp.mmt,0,sizeof(tmp.mmt));
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=n;k++)
			{
				tmp.mmt[i][j]+=a.mmt[i][k]*b.mmt[k][j];
				tmp.mmt[i][j]%=10007;
			}
		}
	} 
	return tmp;
}
void mtqkpow(int a,int n)
{
	for(int i=1;i<=n;i++) ans.mmt[i][i]=1;
	while(a)
	{
		if(a&1) ans=mul(ans,res,n);
		res=mul(res,res,n);
		a>>=1;
	} 
}
int main()
{
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		memset(ans.mmt,0,sizeof(ans.mmt));
		memset(res.mmt,0,sizeof(res.mmt));
		scanf("%d%d%d%d",&hn,&ha,&hb,&hc);
		if(hn<=2){
			printf("Case %d: 0\n",i);
			continue;
		}
		res.mmt[1][1]=ha;
		res.mmt[1][3]=hb;
		res.mmt[1][4]=hc;
		res.mmt[2][1]=1;
		res.mmt[3][2]=1;
		res.mmt[4][4]=1;
		mtqkpow(hn-1,4);
		mt m;
		memset(m.mmt,0,sizeof(m.mmt));
		m.mmt[1][1]=hc;
		m.mmt[4][1]=1;
		int anser=0;
		for(int k=1;k<=4;k++)
		{
			anser+=ans.mmt[3][k]*m.mmt[k][1];
			anser%=10007;
		}
		printf("Case %d: %d\n",i,anser);
	}
}

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注