题意:
给出f[1]=a;f[2]=b;f[n]=f[n-1]+2*f[n-2]+i*i*i*i;问f[n]对2147493647取模的值,n的范围到2的31次。
思路:
由于n的范围过大,必须要用矩阵快速幂求解。难点在于构造矩阵。一开始我的想法是把i的四次分别用(i-1)的四次、三次、二次、一次、零次表示,来构造矩阵,结果一直错,后来看了网上有人是把i+1的四次用i来表示来构造的矩阵,于是我换了下矩阵,就过了,至今不明白原来构造的矩阵为什么就不行。
矩阵如下:
ps: 2147493647记得用 unsigned int,别问我为什么知道QAQ
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const unsigned int mod=2147493647;
struct p
{
long long x[8][8];
} u, o;
void init(long long r[][10], long long y[][10])
{
int i, j;
for(i=0; i<=6; i++)
{
for(j=0; j<=6; j++)
{
u.x[i][j]=y[i][j];
}
}
for(i=0; i<=6; i++)
{
for(j=0; j<=6; j++)
{
o.x[i][j]=r[i][j];
}
}
}
p multi(p a, p b)
{
int i, j, k;
p c;
for(i=0; i<7; i++)
{
for(j=0; j<7; j++)
{
long long sum=0;
for(k=0; k<=6; k++)
{
sum=(sum+(a.x[i][k]*b.x[k][j])%mod)%mod;
}
c.x[i][j]=sum;
}
}
return c;
}
p rec_quickmod(p a, int n)
{
p b;
memset(b.x, 0, sizeof(b.x));
int i, j;
for(i=0; i<=6; i++)b.x[i][i]=1;
while(n)
{
if(n%2)b=multi(b,a);
n/=2;
a=multi(a,a);
}
return b;
}
int main()
{
int t;
scanf("%d",&t);
int i, j;
long long x[8][10]= {{1,1,0,0,0,0,0}, {2,0,0,0,0,0,0}, {1,0,1,0,0,0,0}, {0,0,4,1,0,0,0}, {0,0,6,3,1,0,0}, {0,0,4,3,2,1,0},{0,0,1,1,1,1,1}};
long long y[8][10]= {{0,0,81,27,9,3,1}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}};
while(t--)
{
int n;
long long a, b;
scanf("%d%lld%lld", &n, &a, &b);
if(n==1){printf("%lld\n", a);continue;}
if(n==2){printf("%lld\n", b);continue;}
y[0][0]=b;
y[0][1]=a;
init(x, y);
p c=rec_quickmod(o,n-2);
p ans=multi(u,c);
// for(i=0; i<7; i++)
// {
// for(j=0; j<7; j++)
// {
// printf("%lld ", ans.x[i][j]);
// }
// printf("\n");
// }
printf("%lld\n", ans.x[0][0]);
}
return 0;
}