soj#551 loj#2833 帐篷
分析
dp[i][j]表示考虑了i行j列的方案数
我们每次考虑三种情况:
一个点自己放
两个点在同一行
两个点在同一列
代码
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
#define add(x,y) x=(x+y)%mod
int dp[3010][3010],n,m;
int main(){
int i,j,k;
scanf("%d%d",&n,&m);
dp[0][0]=1;
for(i=1;i<=n;i++)dp[i][0]=1;
for(i=1;i<=m;i++)dp[0][i]=1;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
add(dp[i][j],dp[i-1][j]);
add(dp[i][j],4ll*j*dp[i-1][j-1]%mod);
if(i>1)add(dp[i][j],1ll*j*(i-1)%mod*dp[i-2][j-1]%mod);
if(j>1)add(dp[i][j],1ll*j*(j-1)/2%mod*dp[i-1][j-2]%mod);
}
cout<<dp[n][m]-1<<"\n";
return 0;
}