E. Omkar and Forest
题意
一个矩阵,要求矩阵的相邻数字之差最大为 1 1 1 ,如果数字非零,那么至少严格大于其中一个相邻的数字。给出一个矩阵,要求填满这个矩阵,问有几种方案。
题解
在给出的 #
的子集中选择一部分为0
,那么剩下的非零的值是确定的,非零的单元值等于到最近的0
的距离。
- 对于一个非零单元,这个单元到最近的
0
的值为 d d d,那么这个非零单元的值不可能大于 d d d ; - 这个非零单元的值不可能大于
d
d
d:假设大于
d
d
d ,从这个单元格到最近的
0
,每次移动一步最多减一,所以单元格的值不可能大于 d d d ; - 这个非零单元的值不可能小于 d d d:假设小于 d d d,由于相邻单元至少有一个严格小于这个单元的值,那么一定可以通过小于 d d d 的步数到达一个值为 0 0 0 的单元,与条件矛盾;
- 所以每次选择一些
#
为 0 0 0 ,剩下的单元格都是确定的; - 注意要减掉全部非零的情况。
代码
#include <bits/stdc++.h>
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;
const ll mod = 1e9 + 7;
char s[maxn][maxn];
ll powmod(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1) ans = ans * a % mod;
b >>= 1;
a = a * a % mod;
}
return ans;
}
int main() {
#ifdef LOCAL
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
int cnt = 0;
rep(i, 1, n) {
scanf("%s", s[i] + 1);
rep(j, 1, m) cnt += (s[i][j] == '#');
}
printf("%lld\n", powmod(2, cnt) - (cnt == n * m));
}
return 0;
}