题解:P9131 [USACO23FEB] Problem Setting P
我们把每一列看作一个行编号的集合
尝试 DP 这个东西:设
其中
我们一层一层转移,即按照
#include <bits/stdc++.h>
using namespace std;
const int N = 4e6 + 10, P = 1e9 + 7;
int n, m;
int s[N];
int f[N], g[N];
int cnt[N];
vector<int> state[N];
int sum[N];
int main() {
g[0] = 0;
g[1] = 1;
for (int i = 2; i < N; ++ i ) {
g[i] = (1ll * i * (g[i - 1] + 1) % P) % P;
}
cin >> n >> m;
for (int i = 0; i < m; ++ i ) {
for (int j = 0; j < n; ++ j ) {
char c;
cin >> c;
s[j] |= (c == 'H') << i;
}
}
for (int i = 0; i < n; ++ i ) {
cnt[s[i]] ++ ;
}
for (int i = 0; i < (1 << m); ++ i )
state[__builtin_popcount(i)].push_back(i);
f[0] = g[cnt[0]];
for (int i = 1; i <= m; ++ i ) {
for (int j = 0; j < (1 << m); ++ j ) sum[j] = f[j];
for (int j = 0; j < m; ++ j )
for (int k = 0; k < 1 << m; ++ k )
if (k >> j & 1) sum[k] = (sum[k] + sum[k ^ (1 << j)]) % P;
for (int k : state[i]) {
f[k] = 1ll * (sum[k] + 1) * g[cnt[k]] % P;
}
}
int res = 0;
for (int i = 0; i < (1 << m); ++ i ) {
res = (res + f[i]) % P;
}
cout << res;
return 0;
}