Hopefully this problem will not make you love mahjong disappear
We count the number of times each brand Ke to appear, no statistics are a few cards
Sentenced to a deck of cards and can not be similar to this question
For this question:
Set \ (f [i] [j ] [k] [0/1] \) represents the former \ (I \) kinds of cards, Junko \ ((i-1, i , i + 1) \) appeared \ (j \) times, Junko \ ((i, i + 1 , i + 2) \) appeared \ (k \) times, with / without face up to the number of bird head. Transfer is relatively simple
We Ke to find \ (i \) This dimension is less importantForced dp value does not exceed \ (4 \) (more than \ (4 \) to no avail), bird head count does not exceed \ (7 \) (similar), search Ke burst to the seizure of a different nature of the state, a total of \ (2091 \) a
Ke Ke to add to the back of each state (x \ in [0,4] \ ) \ Zhang +1 point cards, which Ke to form an automatic machine,We called her and unlicensed automatic machine
We each get a state, Ke to go on and unlicensed automatic machine, and can determine whether
We set \ (dp [i] [j ] [k] \) indicate seen before \ (i \) kinds of cards, in and on the unlicensed automatic machine \ (j \) state, has touched \ (k \) Zhang brand, not the number of types of Hu, the final count to the expectations on Ke
We Ke to use an array to scroll \ (i \) roll out optimized space
#include <bits/stdc++.h>
#define mod 998244353
#define N 405
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int Min(register int a,register int b)
{
return a<b?a:b;
}
inline int Max(register int a,register int b)
{
return a>b?a:b;
}
struct node{
int f[3][3][2],cnt;
inline void init()
{
memset(f,-1,sizeof(f));
f[0][0][0]=cnt=0;
}
inline int hu()
{
if(cnt>=7)
return 1;
for(register int i=0;i<3;++i)
for(register int j=0;j<3;++j)
if(f[i][j][1]>=4)
return 1;
return 0;
}
}rt,S[2100];
bool operator < (node a,node b){
if(a.cnt!=b.cnt)
return a.cnt<b.cnt;
for(register int i=0;i<3;++i)
for(register int j=0;j<3;++j)
for(register int k=0;k<2;++k)
if(a.f[i][j][k]!=b.f[i][j][k])
return a.f[i][j][k]<b.f[i][j][k];
return 0;
}
int tot=0;
map<node,int> ma;
inline node trans(register node u,register int w)
{
node v;
v.init();
v.cnt=Min(u.cnt+(w>=2),7);
for(register int i=0;i<3;++i)
for(register int j=0;j<3;++j)
{
if(~u.f[i][j][0])
{
for(register int k=0;k<3&&i+j+k<=w;++k)
v.f[j][k][0]=Max(v.f[j][k][0],Min(u.f[i][j][0]+i+(w-i-j-k>=3),4));
if(w>=2)
for(register int k=0;k<3&&i+j+k<=w-2;++k)
v.f[j][k][1]=Max(v.f[j][k][1],Min(u.f[i][j][0]+i,4));
}
if(~u.f[i][j][1])
for(register int k=0;k<3&&i+j+k<=w;++k)
v.f[j][k][1]=Max(v.f[j][k][1],Min(u.f[i][j][1]+i+(w-i-j-k>=3),4));
}
return v;
}
inline void build(register node u)
{
if(u.hu())
return;
if(ma.find(u)!=ma.end())
return;
ma[u]=++tot;
S[tot]=u;
for(register int i=0;i<=4;++i)
build(trans(u,i));
}
int n,s[N],ans;
int fac[N],inv[N],invf[N],tr[2100][5],f[2][2100][N];
inline int C(register int n,register int m)
{
return 1ll*fac[n]*invf[m]%mod*invf[n-m]%mod;
}
int main()
{
rt.init();
build(rt);
invf[0]=inv[0]=inv[1]=fac[0]=1;
for(register int i=1;i<N;++i)
fac[i]=1ll*fac[i-1]*i%mod;
for(register int i=2;i<N;++i)
inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
for(register int i=1;i<N;++i)
invf[i]=1ll*invf[i-1]*inv[i]%mod;
n=read();
for(register int i=1;i<=13;++i)
++s[read()],read();
for(register int i=1;i<=tot;++i)
for(register int j=0;j<=4;++j)
tr[i][j]=ma[trans(S[i],j)];
f[0][1][0]=1;
for(register int i=1,sum=0;i<=n;++i)
{
int now=i&1,pre=now^1;
memset(f[now],0,sizeof(f[now]));
for(register int j=1;j<=tot;++j)
for(register int k=s[i];k<=4;++k)
{
if(!tr[j][k])
continue;
int w=1ll*C(4-s[i],k-s[i])*fac[k-s[i]]%mod;
for(register int l=0;l<=4*n-k;++l)
{
if(!f[pre][j][l])
continue;
f[now][tr[j][k]][l+k]=(0ll+f[now][tr[j][k]][l+k]+1ll*f[pre][j][l]*w%mod*C(k+l-sum-s[i],k-s[i])%mod)%mod;
}
}
sum+=s[i];
}
for(register int i=13,w=1;i<=4*n;++i)
{
int now=0;
for(register int j=1;j<=tot;++j)
now=(0ll+now+f[n&1][j][i])%mod;
ans=(0ll+ans+1ll*now*w%mod)%mod;
w=1ll*w*inv[4*n-i]%mod;
}
write(ans);
return 0;
}