题目链接:点击打开链接
题目大意:求
f(n) = f(n−1)+2*f(n−2)+n4
,其中
f(1)=a,f(2)=b
思路:
首先一看这个题目,很容易想到构造矩阵:那么我们现在来分析一下怎么构造这个矩阵,那么
(n+1)4 = n4+4n3+6n2+4n+1
所以光
(n+1)4
这个矩阵就能构造出
5∗5
的一个矩阵来, 然后
f(n) = f(n−1)+2∗f(n−2)
这个是
2∗2
的矩阵,所以构造出来就应该是
7∗7
的转移矩阵
A
:
{f(n),f(n−1),n4,n3,n2,n,1}∗A={f(n+1),f(n),(n+1)4,(n+1)3,(n+1)2,(n+1),1}
然后
f(n+1) = f(n)+2∗f(n−1)+(n+1)4
, 可得矩阵
A:
⎛⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜1214641100000000146410001331000012100000110000001⎞⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟
然后
f(n+1) = {{f(n),f(n−1),n4,n3,n2,n,1}∗An−2}.
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include<iostream>
using namespace std;
#define ll long long
#define N 25
#define maxn 300
ll mod=2147493647;
ll n,a,b;
struct Matrix
{
ll r,c;
ll m[N][N];
Matrix(){}
Matrix(ll r,ll c):r(r),c(c){}
Matrix operator *(const Matrix& B)//乘法
{
Matrix T(r,B.c);
for(int i=1;i<=T.r;i++)
{
for(int j=1;j<=T.c;j++)
{
ll tt = 0;
for(int k=1;k<=c;k++)
tt +=( m[i][k]*B.m[k][j]) % mod;
T.m[i][j] = tt % mod;
}
}
return T;
}
Matrix operator =(const Matrix& B)//复制
{
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
m[i][j] = B.m[i][j];
}
}
}
Matrix operator +(const Matrix& B)//加法
{
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
m[i][j]+= B.m[i][j];
}
}
}
Matrix Unit(ll h) // 对角线矩阵
{
Matrix T(h,h);
memset(T.m,0,sizeof(T.m));
for(int i=1;i<=h;i++)
T.m[i][i] = 1;
return T;
}
Matrix Pow(ll n) //矩阵幂
{
Matrix P = *this,Res = Unit(r);
while(n!=0)
{
if(n&1)
Res =Res*P;
P = P*P;
n >>= 1;
}
return Res;
}
void Print()//输出
{
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
printf("%d ",m[i][j]);
printf("\n");
}
}
}Single;
ll num[55]={0,1,2,1,4,6,4,1,1,0,0,0,0,0,0,0,0,1,4,6,4,1,0,0,0,1,3,3,1,0,0,0,0,1,2,1,0,0,0,0,0,1,1,0,0,0,0,0,0,1};
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld",&n,&a,&b);
if(n==1){
printf("%lld",a%mod);
continue;
}
if(n==2)
{
printf("%lld",b%mod);
continue;
}
Matrix pre(7,1);
pre.m[1][1]=b;
pre.m[2][1]=a;
pre.m[3][1]=16;
pre.m[4][1]=8;
pre.m[5][1]=4;
pre.m[6][1]=2;
pre.m[7][1]=1;
Matrix a(7,7);
for(int i=1;i<=7;i++)
for(int j=1;j<=7;j++)
{
a.m[i][j]=num[(i-1)*7+j];
}
a=a.Pow(n-2);
a=a*pre;
printf("%lld\n",a.m[1][1]);
}
return 0;
}