題目背景
金企鵝同窗很是擅長用1*2的多米諾骨牌覆蓋棋盤的題。有一天,正 在背四六級單詞的他突然想:既然兩個格子的積木叫「多米諾(domino)」,那 麼三個格子的的積木必定叫「三米諾(tromino)」了!用三米諾覆蓋棋盤的題 怎麼作呢?dom
題目描述
用三米諾覆蓋3n 的矩形棋盤,共多少種方案?三米諾可旋轉;兩種 方案不一樣當且僅當這兩種圖案直接覆蓋在一塊兒沒法重疊。優化
輸入輸出格式
輸入格式:
一行一個整數n(n<=10^40000),表示棋盤列數。url
輸出格式:
一行一個整數,表示方案數,對998244353 取模。spa
輸入輸出樣例
輸入樣例#1
2.net
輸出樣例#1
3code
輸入樣例#2
3get
輸出樣例#2
10string
輸入樣例#3
29it
輸出樣例#3
543450786io
說明
對於10% 的數據,n <=5;
對於30% 的數據,n <=10^6;
對於40% 的數據,n <=20001000;
對於60% 的數據,n <=10^9;
對於80% 的數據,n <=10^1000
對於100% 的數據,n<=10^40000。
請在oeis搜索A134438數列並用矩陣,十進制快速冪優化 標程裏的矩陣是手玩出來的...可能會寫?
標程
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int tb[9][9] = { {1, 2, 1, 1, 0, 0, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 0}, {0, 1, 0, 0, 1, 0, 0, 0, 0}, }; const int N = 1000005, P = 998244353; char s[N]; int n; struct matrix { ll g[9][9]; matrix(){ memset(g, 0, sizeof(g)); } matrix operator * (const matrix &b) const { matrix c; for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++) for(int k = 0; k < 9; k++) c.g[i][j] = (c.g[i][j] + g[i][k] * b.g[k][j]) % P; return c; } } mtx, ans, tmp, pw[10]; int main(){ freopen("tromino.in","r",stdin);freopen("tromino.out","w",stdout); scanf("%s", s); n = strlen(s); for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++) mtx.g[i][j] = tb[j][i]; for(int i = 0; i < 9; i++) pw[0].g[i][i] = 1; for(int i = 1; i <= 9; i++) pw[i] = pw[i - 1] * mtx; ans = pw[0]; for(int i = 0; i < n; i++){ tmp = ans = ans * ans; ans = ans * ans; ans = ans * ans * tmp * pw[s[i] - '0']; } printf("%lld\n", ans.g[0][0]); return 0; }