有n个人,第i个人初始拥有第i号球,
两两之间可以交换球,
第一种人最多能交换1次
第二种人最多能交换2次,
dp[i][j]表示第一种人i个,第二种人j个的情况总数
不妨设第一种人1~i,第二种人i+1~i+j,我们只关注第一个人手中的球
1.手中的球为1 dp[i-1][j]
2.手中的球为i+1~i+j j*dp[i][j-1]
3.手中的球为2~i 枚举这个球在传递过程中经过了几个人
∑jk=0A[j][k]∗dp[i−2][j−k]
A[j][k]表示全排列A(j,k)
#include<cstdio>
#include<iostream>
using namespace std;
typedef __int64 LL;
const int mod=1e9+7;
const int N=500+10;
LL dp[N][N];
void init(int n){
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
dp[i][j]=0;
if(!i&&!j){
dp[i][j]=1;
continue;
}
if(i==0){
dp[i][j]+=dp[i][j-1]*j;dp[i][j]%=mod;continue;
}
dp[i][j]+=dp[i-1][j];dp[i][j]%=mod;
if(j){
dp[i][j]+=j*dp[i][j-1];dp[i][j]%=mod;
}
if(i>=2){
LL now=i-1;
for(int k=0;k<=j;k++){
dp[i][j]+=now*dp[i-2][j-k];dp[i][j]%=mod;
now*=(j-k);now%=mod;
}
}
}
}
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
int n;
init(500);
while(scanf("%d",&n)!=EOF){
int b=0;
for(int i=0;i<n;i++){
int a;scanf("%d",&a);
if(a==1){
b++;
}
}
printf("%I64d\n",dp[b][n-b]);
}
return 0;
}