题目大意
给你一个3*n网格图。
你有m个士兵,每个士兵会对3*3的范围内进行攻击,攻击矩阵初始给定。
有多少种放置士兵的方法,使得士兵互不攻击。
DP
很显然能dp
这个dp还很显然能NTT优化
但是常数大显然不一定跑得过暴力
于是我们就暴力吧(雾
#pragma GCC optimize(2)
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int mo=998244353,maxn=2500+10;
int f[2][maxn*3][10];
int a[10],one[10],dis[10][10],d[5][5];
int cc[10][10],len[10];
bool c[5][5],ha[5][5],bz[10],czy,gjx,wzd;
int i,j,k,l,r,t,x,y,n,m,top,ans,now,down,up;
int qsm(int x,int y){
if (!y) return 1;
int t=qsm(x,y/2);
t=(ll)t*t%mo;
if (y%2) t=(ll)t*x%mo;
return t;
}
void work(){
ans=1;
fo(i,1,3*n) ans=(ll)ans*i%mo;
fo(i,1,m) ans=(ll)ans*qsm(i,mo-2)%mo;
fo(i,1,3*n-m) ans=(ll)ans*qsm(i,mo-2)%mo;
printf("%d\n",ans);
}
int main(){
one[1]=one[2]=one[4]=1;
one[3]=one[5]=one[6]=2;
one[7]=3;
scanf("%d%d",&n,&m);
gjx=1;
fo(i,0,2)
fo(j,0,2){
scanf("%d",&c[i][j]);
if (c[i][j]&&(i!=1||j!=1)) gjx=0;
}
ha[2][0]=c[0][0];
ha[2][2]=c[2][0];
ha[0][2]=c[2][2];
ha[0][0]=c[0][2];
ha[1][0]=c[0][1];
ha[2][1]=c[1][0];
ha[1][2]=c[2][1];
ha[0][1]=c[1][2];
ha[1][1]=c[1][1];
fo(i,0,2)
fo(j,0,2)
c[i][j]=ha[i][j];
if (gjx){
work();
return 0;
}
fo(i,0,7){
if (!c[0][1]&&!c[2][1]){
wzd=1;
a[++top]=i;
continue;
}
if ((i&1)&&(i&2)) continue;
if ((i&2)&&(i&4)) continue;
a[++top]=i;
}
fo(i,1,top) bz[a[i]]=1;
fo(i,0,7)
fo(j,0,7){
if (!bz[i]||!bz[j]) continue;
fo(k,0,2)
if ((i&(1<<k))) d[k][0]=1;else d[k][0]=0;
fo(k,0,2)
if ((j&(1<<k))) d[k][1]=1;else d[k][1]=0;
czy=1;
fo(k,0,2)
fo(l,0,1)
if (d[k][l])
fo(x,-1,1)
fo(y,-1,1)
if ((x||y)&&k+x>=0&&k+x<=2&&l+y>=0&&l+y<=1&&c[x+1][y+1]&&d[k+x][l+y]) czy=0;
if (czy) dis[i][j]=1;
}
fo(i,1,top){
fo(j,1,top)
if (dis[a[i]][a[j]]) cc[a[i]][++len[a[i]]]=a[j];
}
now=0;
fo(i,1,top) f[now][one[a[i]]][a[i]]=1;
fo(i,1,n-1){
down=max(m-3*(n-i),0);
if (wzd) up=min(3*i,m);else up=min(2*i,m);
//down=0;
fo(k,1,top)
fo(j,down,up)
f[1-now][j][a[k]]=0;
/*fo(j,0,m)
fo(k,1,top)
if (f[now][j][a[k]])
fo(l,1,top)
if (dis[a[k]][a[l]]){
f[1-now][j+one[a[l]]][a[l]]+=f[now][j][a[k]];
if (f[1-now][j+one[a[l]]][a[l]]>=mo) f[1-now][j+one[a[l]]][a[l]]-=mo;
}*/
fo(j,down,up)
fo(k,1,top){
x=a[k];
if (f[now][j][x])
fo(l,1,len[x]){
r=cc[x][l];
//if (dis[x][r]){
y=j+one[r];
f[1-now][y][r]+=f[now][j][x];
if (f[1-now][y][r]>=mo) f[1-now][y][r]-=mo;
// }
}
}
now=1-now;
}
fo(i,1,top){
ans+=f[now][m][a[i]];
if (ans>=mo) ans-=mo;
}
printf("%d\n",ans);
}