前段时间学了学矩阵模乘,大致明白了这个原理。第一次来做这种题,表示写的非常头疼!确切说是调试的很头疼!
昨天下午写好的代码,提交后---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;
}