链接:https://codeforces.com/contest/1228/problem/B
来源:Codeforces Round #589 (Div. 2)
题意:给出 n × m 大小的格子
r[i] 表示第 i 行从第 1 个格子开始连续的有 r[i] 个黑格子。
c[i] 表示第 i 列从第 1 个格子开始连续的有 c[i] 个黑格子。
能有多少种方案数满足上述的约束条件?如果不满足输出 -1。
思路:定义一个表示状态的矩阵全部初始化为 -1,表示某一个格子是不确定的状态,如果是 0 ,表示这个格子是白色,如果是 1 ,表示这个格子是黑色。此题的重点在于判断已经有了状态的格子后面是否冲突,注意每次确定状态之前都要判断格子是否已经有了某种状态。如果不存在冲突,那么必定有 cnt 个格子是在不确定的状态之下的。这 cnt 个格子决定了方案数。C(cnt, 0) + C(cnt, 1) + C(cnt, 2)+···+C(cnt, cnt) = 2cnt,表示这些格子可以不选,任选一个,任选两个···直到 cnt 个。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int Max_n = 1e3 + 10;
int a[Max_n][Max_n], r[Max_n], c[Max_n];
ll qpow(ll a, ll b) {
ll ans = 1, res = a;
while(b) {
if(b & 1) ans = ans * res % mod;
res = res * res % mod;
b >>= 1;
}
return ans % mod;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
memset(a, -1, sizeof(a));
bool flag = true;//判断冲突
for(int i = 1; i <= n; i++) scanf("%d", &r[i]);
for(int i = 1; i <= m; i++) scanf("%d", &c[i]);
for(int i = 1; i <= n; i++) {
if(!r[i]) {
if(a[i][1] == 1) flag = false;
a[i][1] = 0;
}
int j = 1;
for(; j <= r[i]; j++) {
if(a[i][j] == 0) flag = false;
a[i][j] = 1;
}
if(a[i][j] == 1) flag = false;
a[i][j] = 0;
}
for(int j = 1; j <= m; j++) {
if(!c[j]) {
if(a[1][j] == 1) flag = false;
a[1][j] = 0;
}
int i = 1;
for(; i <= c[j]; i++) {
if(a[i][j] == 0) flag = false;
a[i][j] = 1;
}
if(a[i][j] == 1) flag = false;
a[i][j] = 0;
}
if(!flag) puts("0");
else {
int cnt = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++)
if(a[i][j] == -1) cnt++;
}
ll ans = qpow(2, cnt);
printf("%lld\n", ans);
}
return 0;
}