HDU-6470 Count (构造矩阵+矩阵快速幂)
題目鏈接
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太大,需要用快速冪的log(N)log(N)log(N)來優化。
首先遞推公式:F(N)=2?F(N?2)+F(N?1)+N3F(N) = 2*F(N-2) + F(N-1) + N^3F(N)=2?F(N?2)+F(N?1)+N3
下面構造矩陣來優化:
N3=(N?1+1)3=C30(N?1)3+C31(N?1)2+C32(N?1)1+C33(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)N3N2N1N0}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?
這是我們需要一個矩陣
{01000021C30C31C32C3300C30C31C32C33000C20C21C220000C10C1100000C33}\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\} ????????????????020000?110000?0C30?C30?000?0C31?C31?C20?00?0C32?C32?C21?C10?0?0C33?C33?C22?C11?C33??????????????????
這時狀態111就可以通過矩陣得到狀態222
初始矩陣{F(1)F(2)23222120}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?
Ans=matrixn?2?matrix3Ans = matrix^{n-2} * matrix_3Ans=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); #endifios::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; }總結
以上是生活随笔為你收集整理的HDU-6470 Count (构造矩阵+矩阵快速幂)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hihoCoder #1467 : 2-
- 下一篇: hihoCoder #1468 : 2-