dp[i][j] : 还有 i 个1,进行了 j 次翻转操作的方法数。
Source : Regionals 2014 >> Asia - Kuala Lumpur
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define prt(k) cout<<#k" = "<<k<<endl;
const int N = 2333;
typedef long long ll;
const ll mod = 1e9+7;
ll dp[N][2];
char s[N];
int n, m;
void add(ll &a, ll b) { a=(a+b)%mod; }
int main()
{
int re; cin>>re;
int ca = 1;
while (re--)
{
cin>>n>>m;
int cnt = 0;
for (int i=0;i<n;i++) {
int x; scanf("%d", &x);
if(x==1) cnt++;
}
int now = 0;
memset(dp ,0, sizeof dp);
dp[cnt][now] = 1;
for (int j=0;j<m;j++)
{
for(int i=n;i>=0;i--)
{
if(i>0)
{
add(dp[i-1][1-now], dp[i][now] * i % mod);
}
add(dp[i+1][1-now], dp[i][now] * (n-i) % mod);
}
for(int i=0;i<=n;i++) dp[i][now] = 0;
now=1-now;
}
printf("Case #%d: %lld\n",ca++, dp[0][now]);
}
}