Codeforces Round #724 (Div. 2) E. Omkar and Forest

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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43860866/article/details/118062317
今日推荐