题目背景
金企鹅同窗很是擅长用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; }