[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;
}
原文地址:https://www.cnblogs.com/elpsycongroo/p/7797104.html