决战
解法1:DP+常数优化
f[i][S][j]表示i列,第i列状态为S,放了j个哲学家
第一维可以滚动
f[i][S][j]+=f[i-1][S'][l]
对于S和S'只枚举合法的,这可以预处理出来
然后枚举j时可以算出上下界
解法2:
矩阵+NTT优化DP
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 lol f[2][8][7501],Mod=998244353,ans; 9 int n,m,pw[4],v[8],mp[8][8],num[8],s[8][8],pre,nxt; 10 int main() 11 { 12 int i,j,k,l; 13 cin>>n>>m; 14 pw[1]=1;pw[2]=2;pw[3]=4; 15 num[0]=0;num[1]=1;num[2]=1;num[3]=2;num[4]=1;num[5]=2;num[6]=2;num[7]=3; 16 for (i=1; i<=3; i++) 17 for (j=1; j<=3; j++) 18 scanf("%d",&s[i][j]); 19 for (i=0; i<=7; i++) 20 { 21 v[i]=1; 22 int tmp[5]= {0}; 23 for (j=1; j<=3; j++) 24 if (i&pw[j]) 25 { 26 tmp[j-1]|=s[2][1]; 27 tmp[j+1]|=s[2][3]; 28 } 29 for (j=1; j<=3; j++) 30 if ((i&pw[j])&&tmp[j]) v[i]=0; 31 } 32 for (i=0; i<=7; i++) 33 if (v[i]) 34 { 35 for (j=0; j<=7; j++) 36 if (v[j]) 37 { 38 int tmp1[5]= {0},tmp2[5]= {0}; 39 mp[i][j]=1; 40 for (k=1; k<=3; k++) 41 if (pw[k]&i) 42 { 43 tmp1[k-1]|=s[3][1]; 44 tmp1[k+1]|=s[3][3]; 45 tmp1[k]|=s[3][2]; 46 } 47 for (k=1; k<=3; k++) 48 if (pw[k]&j) 49 { 50 tmp2[k-1]|=s[1][1]; 51 tmp2[k+1]|=s[1][3]; 52 tmp2[k]|=s[1][2]; 53 } 54 for (k=1; k<=3; k++) 55 if (tmp2[k]&&(i&pw[k])||tmp1[k]&&(j&pw[k])) 56 mp[i][j]=0; 57 } 58 } 59 pre=0;nxt=1; 60 for (i=0; i<=7; i++) 61 f[pre][i][num[i]]=v[i]; 62 for (i=2; i<=n; i++) 63 { 64 int a=min(i*3,m),b=max(0,m-(n-i+1)*3); 65 for (j=0; j<=7; j++) 66 if (v[j]) 67 { 68 for (k=0; k<=7; k++) 69 if (v[k]&&mp[j][k]) 70 { 71 for (l=b; l<=a-num[k]; l++) 72 { 73 f[nxt][k][l+num[k]]+=f[pre][j][l]; 74 if (f[nxt][k][l+num[k]]>=Mod) 75 f[nxt][k][l+num[k]]-=Mod; 76 } 77 } 78 } 79 for(j=0; j<=7; j++) 80 if(v[j]) 81 for(k=b; k<=a; k++)f[pre][j][k]=0; 82 swap(nxt,pre); 83 } 84 for (i=0; i<=7; i++) 85 ans=ans+f[pre][i][m],ans%=Mod; 86 cout<<ans; 87 }