第一反应状压DP,然而N≤100…
解决问题的关键在于(摘自某题解的一段话):
其实我们不用管到底哪些列有一个有两个炮,只用看到现在有几列是一个炮,有几列没有炮、两个炮
有了这个想法以后,DP方程就不难写出了【不难个鬼…细节超多OLZ】.
AC code:
#include <cstdio>
typedef long long ll;
const ll N=110;
const ll TOMOD=9999973;
ll n,m,ans;
ll f[N][N][N];
int main(){
scanf("%lld%lld",&n,&m);
f[0][m][0]=1;
for(ll i=1;i<=n;i++){
for(ll j=0;j<=m;j++){
for(ll k=0;k+j<=m;k++){
f[i][j][k]=(f[i][j][k]+f[i-1][j][k])%TOMOD;
if(k) f[i][j][k]=(f[i][j][k]+f[i-1][j+1][k-1]*(j+1))%TOMOD;
f[i][j][k]=(f[i][j][k]+f[i-1][j][k+1]*(k+1))%TOMOD;
if(k>1) f[i][j][k]=(f[i][j][k]+f[i-1][j+2][k-2]*(j+2)*(j+1)/2)%TOMOD;
f[i][j][k]=(f[i][j][k]+f[i-1][j][k+2]*(k+2)*(k+1)/2)%TOMOD;
if(k) f[i][j][k]=(f[i][j][k]+f[i-1][j+1][k]*(j+1)*k)%TOMOD;
}
}
}
for(ll i=0;i<=m;i++){
for(ll j=0;i+j<=m;j++) ans=(ans+f[n][i][j])%TOMOD;
}
printf("%lld\n",ans);
return 0;
}