nyoj301-递推求值(矩阵模乘)

前段时间学了学矩阵模乘,大致明白了这个原理。第一次来做这种题,表示写的非常头疼!确切说是调试的很头疼!

昨天下午写好的代码,提交后---WA,下载了测试数据,昨天晚上开始调试,就在刚刚还是测试数据都不对,无奈的提交一下,竟然AC、、、、、、、

传奇、、、、、神奇、、、、、叹为观止的机器原因又一次重演了。。。。。。搞不清、、、、试试别人的代码全部都是测试数据都不对、、、、、

好吧、、、、、

题意:

递推式:f(x)=a*f(x-2)+b*f(x-1)+c,

给出f(1),f(2),a,b,c,n;求f(n)。0<n<10^9.

分析:

很明显是矩阵模乘。

递推矩阵F1【f(1),f(2),c】



0 a 0

单位矩阵F2【 1 b 0 】

0 1 1



f(n)就是F1*F2^(n-1)的首元素。

代码(不知道可信不,反正AC啦):

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
long long f[3][3];
long long ff[3][3];
long long c;long long f1;long long f2;
//计算两个矩阵的乘积
int Calculate(long long a[3][3],long long b[3][3])
{
	int i,j,k;
	long long x[3][3];
	memset(x,0,sizeof(x));
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
		    long long sum=0;
            for(k=0;k<3;k++)
                sum=(sum+a[i][k]*b[k][j])%1000007;
            x[i][j]=(sum+1000007)%1000007;
        }
	}
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
			a[i][j]=x[i][j];
	}
	return 0;
}
//计算矩阵的n次方
void multiply(long long f[][3],int n)//递归
{
    if(n==1) return ;
	multiply(f,n>>1);Calculate(f,f);
	if(n&1)
	Calculate(f,ff);
}

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		//初始矩阵
		memset(f,0,sizeof(f));
		f[1][0]=1;f[2][1]=1;f[2][2]=1;
		long long n;
		scanf("%lld%lld",&f1,&f2);
        //      a        b        c
		scanf("%lld %lld %lld %lld",&f[0][1],&f[1][1],&c,&n);
		int i,j;
		for(i=0;i<3;i++)
			for(j=0;j<3;j++)
				ff[i][j]=f[i][j];
        if(n>1)
		{
		    multiply(f,n-1);//计算矩阵的n-1次方
		    f[0][0]=f1*f[0][0]%1000007+f2*f[1][0]%1000007+c*f[2][0]%1000007;
		}
		else f[0][0]=f1;
		printf("%lld\n",(f[0][0]%1000007+1000007)%1000007);
	}
	return 0;
}

额、、、、还是不放心呀、附上一个同学的代码吧

留着当成模板看

 
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define mod 1000007
using namespace std;
class matrix{
public:
	matrix(int ff1,int ff2,int aa,int bb,int cc,int nn);
	void _binary(int);
	long long calculate();
	void multiply(long long mat1[3][3],long long mat2[3][3]);
	void copy(long long mat1[3][3],long long mat2[3][3]);
	void put();
private:
	long long mat[3][3],ma1[3][3],ma2[3][3],mid[3][3];
	int a,b,c,f1,f2,n;
};
void matrix::multiply(long long mat1[3][3],long long mat2[3][3]){
	long long sum;
	long long ma[3][3];
	for(int i=0;i<3;++i){
		for(int j=0;j<3;++j){
			sum=0;
			for(int k=0;k<3;++k)
				sum=(sum+mat1[i][k]*mat2[k][j])%mod;
			ma[i][j]=(sum+mod)%mod;
		}
	}copy(ma,mat1);
}
matrix::matrix(int ff1,int ff2,int aa,int bb,int cc,int nn){
	memset(ma1,0,sizeof(ma1));
	memset(mat,0,sizeof(mat));
	memset(ma2,0,sizeof(ma2)); 
	f1=ff1;f2=ff2;a=aa;b=bb;c=cc;n=nn;
	mat[0][0]=ff1;mat[0][1]=ff2;mat[0][2]=cc;
	ma1[0][1]=aa;ma1[1][0]=1;ma1[1][1]=bb;ma1[2][1]=ma1[2][2]=1;
	copy(ma1,mid);
}
long long matrix::calculate(){
	if(n>1){
		_binary(n-1);
		multiply(mat,ma1);
	}
	return (mat[0][0]%mod+mod)%mod;
}
void matrix::_binary(int r){
	if(r==1) return ;
	else {
		_binary(r/2);
		multiply(ma1,ma1);
		if(r%2) multiply(ma1,mid);
	}
}
void matrix::copy(long long mat1[3][3],long long mat2[3][3]){
	for(int i=0;i<3;++i)
		for(int j=0;j<3;++j)
			mat2[i][j]=mat1[i][j];
}
int main()
{
	int t,m,n,a,b,c,f1,f2;
	cin>>t;
	while(t--)
	{
		cin>>f1>>f2>>a>>b>>c>>n;
		matrix mat(f1,f2,a,b,c,n);
		cout<<mat.calculate()<<endl;
	}
	return 0;
}        




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值