题目大意
求 f n = f n − 1 + 2 × f i − 2 + n 4 f_n=f_{n-1}+2\times f_{i-2}+n^4 fn=fn−1+2×fi−2+n4,其中 f 1 = a , f 2 = b f_1=a,f_2=b f1=a,f2=b
思路
如果没有
n
4
n^4
n4,那就是一个异常简单的noip普及组难度,但是现在有了,那怎么办呢?我们考虑
(
n
+
1
)
4
=
n
4
+
4
×
n
3
+
6
×
n
2
+
4
×
n
+
1
(n+1)^4=n^4+4\times n^3+6\times n^2+4\times n+1
(n+1)4=n4+4×n3+6×n2+4×n+1,所以,如果我们把
n
4
n^4
n4也加入初始矩阵,那我们
n
3
,
n
2
,
n
,
1
n^3,n^2,n,1
n3,n2,n,1都加进初始矩阵,而
(
n
+
1
)
3
=
n
3
+
3
×
n
2
+
3
×
n
+
1
,
(
n
+
1
)
2
=
n
2
+
2
×
n
+
1
,
(
n
+
1
)
=
n
+
1
(n+1)^3=n^3+3\times n^2+3\times n+1,(n+1)^2=n^2+2\times n+1,(n+1)=n+1
(n+1)3=n3+3×n2+3×n+1,(n+1)2=n2+2×n+1,(n+1)=n+1,然后,我们就可以构造出初始矩阵和转移矩阵了,大概长成这样:
(
f
2
f
1
3
4
3
3
3
2
3
1
3
0
)
\begin{pmatrix} f_2\\ f_1\\ 3^4\\ 3^3\\ 3^2\\ 3^1\\ 3^0 \end{pmatrix}
⎝⎜⎜⎜⎜⎜⎜⎜⎜⎛f2f13433323130⎠⎟⎟⎟⎟⎟⎟⎟⎟⎞
×
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \times
×
(
1
2
1
0
0
0
0
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
0
1
)
\begin{pmatrix} 1&2&1&0&0&0&0\\ 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&0&1 \end{pmatrix}
⎝⎜⎜⎜⎜⎜⎜⎛110000200000101000004100006310004320001111⎠⎟⎟⎟⎟⎟⎟⎞
我觉得,当
n
=
1
o
r
2
n=1or2
n=1or2的时候需要特判一下,然后顺便开一下long long,但是我错了很多次,主要就是转移矩阵一个笔误码误,废了我的一生,但是样例太弱了,诶~,太菜了
代码
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define Int register int
#define int long long
#define MAXN 10
int mod = 2147493647ll;
struct Matrix
{
int n,m;
int a[MAXN][MAXN];
Matrix(){memset (a,0,sizeof (a));}
Matrix operator * (const Matrix &p)const
{
Matrix New;
New.n = n,New.m = p.m;
for (Int i = 1;i <= New.n;++ i)
for (Int j = 1;j <= New.m;++ j)
for (Int k = 1;k <= m;++ k)
New.a[i][j] = (New.a[i][j] + a[i][k] % mod * p.a[k][j] % mod) % mod;
return New;
}
};
Matrix quick_pow (Matrix a,int b)
{
Matrix res;
res.n = res.m = a.n;
for (Int i = 1;i <= res.n;++ i) res.a[i][i] = 1;
while (b)
{
if (b & 1)
res = res * a;
a = a * a;
b >>= 1;
}
return res;
}
void read (int &x)
{
x = 0;char c = getchar ();int f = 1;
while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}
while (c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + c - '0';c = getchar();}
x *= f;return ;
}
void write (int x)
{
if (x < 0){x = -x;putchar ('-');}
if (x > 9) write (x / 10);
putchar (x % 10 + '0');
}
signed main()
{
Matrix A,B,C;
B.n = B.m = 7;
B.a[1][1] = 1,B.a[1][2] = 2,B.a[1][3] = 1;
B.a[2][1] = 1;
B.a[3][3] = 1,B.a[3][4] = 4,B.a[3][5] = 6,B.a[3][6] = 4,B.a[3][7] = 1;
B.a[4][4] = 1,B.a[4][5] = 3,B.a[4][6] = 3,B.a[4][7] = 1;
B.a[5][5] = 1,B.a[5][6] = 2,B.a[5][7] = 1;
B.a[6][6] = 1,B.a[6][7] = 1;
B.a[7][7] = 1;
int times;
read (times);
while (times --)
{
int N,a,b;
read (N),read (a),read (b);
a %= mod,b %= mod;
if (N == 1)
{
write (a),putchar ('\n');
continue;
}
else if (N == 2)
{
write (b),putchar ('\n');
continue;
}
A.n = 7,A.m = 1;
A.a[1][1] = b,A.a[2][1] = a,A.a[3][1] = 81,A.a[4][1] = 27,A.a[5][1] = 9,A.a[6][1] = 3,A.a[7][1] = 1;
C = quick_pow (B,N - 2) * A;
write (C.a[1][1]),putchar ('\n');
}
return 0;
}