題意:
第一頭牛和第二頭牛的號碼爲 1 和 2,其餘的牛的號碼需要通過公式求得:
f(n) = f(n - 1) + 2 * f(n - 2) + n * n * n , (f(1) = 1,f(2) = 2,分別是第一頭和第二頭)。
題解:
與前幾項有關的加法公式一般都是用矩陣快速冪來解的。。。所以解法就是矩陣快速冪。
很明顯,右矩陣肯定與 f(n - 1)、f(n - 2) 和 n * n * n。
問題來了,怎麼把 n * n * n 轉移爲 (n + 1) * (n + 1) * (n + 1)?直接算。。。可以得到 :
n * n * n + 3 * n * n - 3 * n + 1 = (n + 1) * (n + 1) * (n + 1),所以我們還要有 n * n 、 n 和 1,同理可以得到:
n * n + 2 * n + 1 = (n + 1) * (n + 1)。
所以右矩陣就這麼可以得出來了:
左矩陣根據關係可以得:
推出來就可以直接對左矩陣快速冪,直接輸出。
AC代碼:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = 123456789;
const int maxn = 2000+10;
struct node {
ll mrx[6][6];
node(){}
node(ll mapp[6][6]) {
for(int i = 0; i < 6; i++) {
for(int j = 0; j < 6; j++) {
mrx[i][j] = mapp[i][j];
}
}
}
node(ll x) {
for(int i = 0; i < 6; i++) {
for(int j = 0; j < 6; j++) {
if(i == j) {
mrx[i][j] = x;
} else {
mrx[i][j] = 0;
}
}
}
}
friend node operator * (node a, node b) {
node ans;
for(int i = 0; i < 6; i++) {
for(int j = 0; j < 6; j++) {
ll p = 0;
for(int k = 0; k < 6; k++) {
p = (p + (a.mrx[i][k] * b.mrx[k][j]) % mod) % mod;
}
ans.mrx[i][j] = p;
}
}
return ans;
}
void print() {
for(int i = 0; i < 6; i++) {
for(int j = 0; j < 6; j++) {
cout << mrx[i][j] << " ";
}
cout << endl;
}
}
};
node qpow(node a, ll b) {
node sum(1);
while(b) {
if(b & 1) {
sum = sum * a;
}
a = a * a;
b >>= 1;
}
return sum;
}
int main() {
ll mapp[6][6] = {{1,2,1,0,0,0},
{1,0,0,0,0,0},
{0,0,1,3,-3,1},
{0,0,0,1,2,1},
{0,0,0,0,1,1},
{0,0,0,0,0,1}};
node temp(mapp);
int t;
cin >> t;
while(t--) {
ll n;
cin >> n;
node m = qpow(temp, n - 2);
ll ans[6] = {2,1,27,16,4,1};
for(int i = 0; i < 6; i++) {
ll sum = 0;
for(int j = 0; j < 6; j++) {
sum = (sum + (ans[j] * m.mrx[i][j]) % mod) % mod;
}
ans[i] = sum;
}
cout << ans[0] << endl;
}
}