dp[i][j][k]表示第i行状态,有j个还需要2个1,有k个爱需要1个1,但是因为空间需求太大,所以使用滚动数组。
#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
__int64 dp[2][505][505];
int main(){
//freopen("G://test.txt","r",stdin);
int m,n;
__int64 mod;
while(scanf("%d%d%I64d",&n,&m,&mod)!=EOF){
char temp;
int r[505];
int flag=0;
memset(r,0,sizeof(r));
memset(dp,0,sizeof(dp));
for(int i=0;i<m;++i){
getchar();
for(int j=0;j<n;++j){
scanf("%c", &temp);
if(temp=='1'){
r[j]++;
}
}
}
int x=0;
int y=0;
for(int i =0;i < n;i++)
if(r[i] ==0)
x++;
else if(r[i]==1)
y++;
int now=0;
dp[now][x][y]=1;
for(int i=0;i<n-m;++i){
now^=1;
memset(dp[now],0,sizeof(dp[now]));
for(int j=0;j<=n;++j){
for(int k=0;k<=n;++k){
if(dp[now^1][j][k]==0)
continue;
if(j>=2)
dp[now][j-2][k+2]=(dp[now^1][j][k]*(j*(j-1)/2)+dp[now][j-2][k+2])%mod;
if(k>=2)
dp[now][j][k-2]=(dp[now^1][j][k]*(k*(k-1)/2)+dp[now][j][k-2])%mod;
if(j>=1&&k>=1)
dp[now][j-1][k]=(dp[now^1][j][k]*j*k+dp[now][j-1][k])%mod;
}
}
}
printf("%I64d\n",dp[now][0][0]);
}
return 0;
}