Problem Description
Farmer John有n头奶牛.
某天奶牛想要数一数有多少头奶牛,以一种特殊的方式:
第一头奶牛为1号,第二头奶牛为2号,第三头奶牛之后,假如当前奶牛是第n头,那么他的编号就是2倍的第n-2头奶牛的编号加上第n-1头奶牛的编号再加上自己当前的n的三次方为自己的编号.
现在Farmer John想知道,第n头奶牛的编号是多少,估计答案会很大,你只要输出答案对于123456789取模.
Input
第一行输入一个T,表示有T组样例
接下来T行,每行有一个正整数n,表示有n头奶牛 (n>=3)
其中,T=104,n<=1018
Output
共T行,每行一个正整数表示所求的答案
Sample Input
5
3
6
9
12
15
Sample Output
31
700
7486
64651
527023
思路
求解过程类似于斐波那契数列,这里的N太大,需要用快速幂的
l
o
g
(
N
)
log(N)
log(N)来优化。
首先递推公式:
F
(
N
)
=
2
∗
F
(
N
−
2
)
+
F
(
N
−
1
)
+
N
3
F(N) = 2*F(N-2) + F(N-1) + N^3
F(N)=2∗F(N−2)+F(N−1)+N3
下面构造矩阵来优化:
N
3
=
(
N
−
1
+
1
)
3
=
C
3
0
(
N
−
1
)
3
+
C
3
1
(
N
−
1
)
2
+
C
3
2
(
N
−
1
)
1
+
C
3
3
(
N
−
1
)
0
\begin{aligned} N^3 &= (N-1 + 1) ^ 3\\ &=C_3^0(N-1)^3 + C_3^1(N-1)^2 +C_3^2(N-1)^1 +C_3^3(N-1)^0\\ \end{aligned}
N3=(N−1+1)3=C30(N−1)3+C31(N−1)2+C32(N−1)1+C33(N−1)0
假
设
我
们
已
知
:
{
F
(
N
−
2
)
F
(
N
−
1
)
(
N
−
1
)
3
(
N
−
1
)
2
(
N
−
1
)
1
(
N
−
1
)
0
}
1
需
要
求
:
{
F
(
N
−
1
)
F
(
N
)
N
3
N
2
N
1
N
0
}
2
假设我们已知:\left\{ \begin{aligned} F(N-2)\\ F(N-1)\\ (N-1)^3\\ (N-1)^2\\ (N-1)^1\\ (N-1)^0\\ \end{aligned} \right\}_1 需要求:\left\{ \begin{aligned} F(N-1)\\ F(N)\\ N^3\\ N^2\\ N^1\\ N^0\\ \end{aligned} \right\}_2
假设我们已知:⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧F(N−2)F(N−1)(N−1)3(N−1)2(N−1)1(N−1)0⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎫1需要求:⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧F(N−1)F(N)N3N2N1N0⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎫2
这是我们需要一个矩阵
{
0
1
0
0
0
0
2
1
C
3
0
C
3
1
C
3
2
C
3
3
0
0
C
3
0
C
3
1
C
3
2
C
3
3
0
0
0
C
2
0
C
2
1
C
2
2
0
0
0
0
C
1
0
C
1
1
0
0
0
0
0
C
3
3
}
\left\{ \begin{matrix} 0 & 1 & 0 & 0 & 0 & 0 \\ 2 & 1 & C_3^0 &C_3^1 &C_3^2&C_3^3 \\ 0 & 0 & C_3^0 &C_3^1 &C_3^2&C_3^3\\ 0 & 0 & 0 &C_2^0 &C_2^1&C_2^2\\ 0 & 0 &0 &0 &C_1^0&C_1^1\\ 0 & 0 & 0 &0 &0&C_3^3\\ \end{matrix} \right\}
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧0200001100000C30C300000C31C31C20000C32C32C21C1000C33C33C22C11C33⎭⎪⎪⎪⎪⎪⎪⎬⎪⎪⎪⎪⎪⎪⎫
这时状态
1
1
1就可以通过矩阵得到状态
2
2
2
初 始 矩 阵 { F ( 1 ) F ( 2 ) 2 3 2 2 2 1 2 0 } 3 初始矩阵\left\{ \begin{aligned} F(1)\\ F(2)\\ 2^3\\ 2^2\\ 2^1\\ 2^0\\ \end{aligned} \right\}_3 初始矩阵⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧F(1)F(2)23222120⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎫3
A n s = m a t r i x n − 2 ∗ m a t r i x 3 Ans = matrix^{n-2} * matrix_3 Ans=matrixn−2∗matrix3
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#include <time.h>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i <= n; ++i)
const int maxn = 1044373;
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
const LL mod = 123456789;
// 定义矩阵 重载*
struct ac{
LL a[6][6];
ac operator * (ac b) {
ac t;
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 6; ++j) {
t.a[i][j] = 0;
for (int k = 0; k < 6; ++k) {
t.a[i][j] = (t.a[i][j] + (a[i][k] * b.a[k][j] % mod)) % mod;
}
}
}
return t;
}
}g, m;
// 矩阵快速幂
ac quick(ac tmp, LL x) {
ac t;
mem(t.a, 0);
for (int i = 0; i < 6; ++i) t.a[i][i] = 1;
while (x) {
if (x & 1) t = t * tmp;
tmp = tmp * tmp;
x >>= 1;
}
return t;
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T;
scanf("%d", &T);
g.a[0][1] = 1;
g.a[1][0] = 2;
g.a[1][2] = g.a[1][1] = 1;
g.a[1][3] = g.a[1][4] = 3;
g.a[1][5] = g.a[2][2] = 1;
g.a[2][3] = g.a[2][4] = 3;
g.a[2][5] = g.a[3][3] = 1;
g.a[3][4] = 2;
g.a[3][5] = g.a[4][4] = g.a[4][5] = g.a[5][5] = 1;
m.a[0][0] = 1;
m.a[1][0] = 2;
m.a[2][0] = 8;
m.a[3][0] = 4;
m.a[4][0] = 2;
m.a[5][0] = 1;
while (T--) {
LL n;
scanf("%lld", &n);
if (n == 1 || n == 2) {
printf("1\n");
continue;
}
ac t = quick(g, n-2);
ac ans = t * m;
printf("%lld\n", ans.a[1][0]);
}
return 0;
}