[bzoj4806]炮
解题关键:每一行每一列不能有3个炮。
令$dp[i][j][k]$表示前$i$行有$j$列有1个炮,$k$列有2个炮,状态转移见code
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<iostream> #define p 999983 using namespace std; typedef long long ll; ll c(ll x){return x*(x-1)/2;} ll dp[200][200][200]; int main(){ ll n,m; cin>>n>>m; dp[0][0][0]=1; for(int i=1;i<=n;i++){ for(int j=0;j<=m;j++){ for(int k=0;k<=m-j;k++){ dp[i][j][k]+=dp[i-1][j][k]; if(j) dp[i][j][k]+=dp[i-1][j-1][k]*(m-j-k+1); if(j>1) dp[i][j][k]+=dp[i-1][j-2][k]*c(m-j-k+2); if(k) dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1); if(k>1) dp[i][j][k]+=dp[i-1][j+2][k-2]*c(j+2); if(j&&k) dp[i][j][k]+=dp[i-1][j][k-1]*(m-j-k+1)*j; dp[i][j][k]%=p; } } } ll ans=0; for(int i=0;i<=m;i++){ for(int j=0;j<=m-i;j++){ ans=(ans+dp[n][i][j])%p; } } cout<<ans<<endl; return 0; }