分析:
因为这是道dp题n<=100,第一想到O(n^3)的算法,发现每行每列最多两个炮,f(i,j,k)表示放完第i行,有j列一个炮,与k列两个炮的方案。即可递推。
详细看代码。
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const ll MOD=9999973; const int maxn=110; ll f[maxn][maxn][maxn]; //f(i,j,k)表示放完第i行,有j列一个炮,与k列两个炮的方案 ll C(int n){//C(n,m) m=2 return n*(n-1)/2%MOD; } int main(){ int n,m; cin>>n>>m; f[0][0][0]=1; for(int i=0;i<=n;++i){ for(int j=0;j<=m;++j){ for(int k=0;j+k<=m;++k){ //不放 f[i+1][j][k]+=f[i][j][k]; f[i+1][j][j]%=MOD; //放一个在有一个炮的下面 if(j>=1){ f[i+1][j-1][k+1]+=f[i][j][k]*j%MOD; f[i+1][j-1][k+1]%=MOD; } //放一个在没炮的下面 if(m-j-k>=1){ f[i+1][j+1][k]+=f[i][j][k]*(m-j-k)%MOD; f[i+1][j+1][k]%=MOD; } //放两个一个在有炮一个在没炮 if(m-j-k>=1&&j>=1){ f[i+1][j][k+1]+=f[i][j][k]*(m-j-k)*j%MOD; f[i+1][j][k+1]%=MOD; } //放两个都在有炮的下面 if(j>=2){ f[i+1][j-2][k+2]+=f[i][j][k]*C(j)%MOD; f[i+1][j-2][k+2]%=MOD; } //放两个都在没炮的下面 if(m-j-k>=2){ f[i+1][j+2][k]+=f[i][j][k]*C(m-j-k)%MOD; f[i+1][j+2][k]%=MOD; } } } } ll ans=0; for(int j=0;j<=m;++j){ for(int k=0;k+j<=m;++k){ ans+=f[n][j][k]%MOD; ans%=MOD; } } cout<<ans; return 0; }