顯然選三個以上的連續牌能夠把他們拆分紅三個三張相等的c++
因而能夠壓\((j,k)\)爲有\(j\)個連續兩個的,有\(k\)個連續一個的優化
若是當前有\(i\)張牌,且\(i >= j + k\)spa
那麼能夠\((j,k)\rightarrow (k,(i - j - k) \% 3)\)code
能夠用矩陣乘法優化,每遇到一個有下限的牌面的就再特殊造一個矩陣轉移get
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define ba 47 #define MAXN 5005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 998244353; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } void update(int &x,int y) { x = inc(x,y); } int getid(int x,int y) { return x * 3 + y; } struct Matrix { int f[9][9]; Matrix() {memset(f,0,sizeof(f));} friend Matrix operator * (const Matrix &a,const Matrix &b) { Matrix c; for(int k = 0 ; k < 9 ; ++k) { for(int i = 0 ; i < 9 ; ++i) { for(int j = 0 ; j < 9 ; ++j) { update(c.f[i][j],mul(a.f[i][k],b.f[k][j])); } } } return c; } friend Matrix fpow(Matrix a,int64 c) { Matrix res,t = a; for(int i = 0 ; i < 9 ; ++i) res.f[i][i] = 1; while(c) { if(c & 1) res = res * t; t = t * t; c >>= 1; } return res; } }a,ans,b; int64 n; int C,X; void Solve() { read(n);read(C); for(int i = 0 ; i <= C ; ++i) { for(int j = 0 ; j < 3 ; ++j) { for(int k = 0 ; k < 3 ; ++k) { if(i < j + k) continue; update(a.f[getid(j,k)][getid(k,(i - j - k) % 3)],1); } } } for(int i = 0 ; i < 9 ; ++i) ans.f[i][i] = 1; read(X); int64 k;int t; int64 p = 0; for(int i = 1 ; i <= X ; ++i) { read(k);read(t); ans = ans * fpow(a,k - 1 - p); memset(b.f,0,sizeof(b.f)); for(int h = t ; h <= C ; ++h) { for(int j = 0 ; j < 3 ; ++j) { for(int k = 0 ; k < 3 ; ++k) { if(h < j + k) continue; update(b.f[getid(j,k)][getid(k,(h - j - k) % 3)],1); } } } ans = ans * b; p = k; } if(p < n) ans = ans * fpow(a,n - p); out(ans.f[0][0]);enter; } int main(){ #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }