ARC196B - Torus Loop

B - Torus Loop

妙妙题,考虑一个 \(A\) 瓷砖链接两个相邻的网格正方形棱,\(B\) 链接对边,考虑给每个正方形的边拆点,容易得出 \(A\) 瓷砖中,任意边选择后对边不选;\(B\) 瓷砖中,任意边选择后,对边都选,非对边都不选。最后缩点后的联通块数除以二就是合法的子块,对答案的贡献是 \(2\) 的幂次。

参考代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int N = 4e6 + 10, mod = 998244353;
int n, m, p[N];

ll qpow(ll a, ll k = mod - 2) {
    ll res = 1;
    while (k) {
        if (k & 1) res = res * a % mod;
        k >>= 1;
        a = a * a % mod;
    }
    return res;
}

int up(int x, int y) {
    x %= n; y %= m;
    return (x * 2 * m + y) << 1;
}

int left(int x, int y) {
    x %= n; y %= m;
    return ((x * 2 + 1) * m + y) << 1;
}

int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void add(int x, int y) {
    p[find(x)] = find(y);
}

void addA(int x, int y) {
    add(up(x, y), up(x + 1, y) ^ 1);
    add(up(x, y) ^ 1, up(x + 1, y));
    add(left(x, y), left(x, y + 1) ^ 1);
    add(left(x, y) ^ 1, left(x, y + 1));
}

void addB(int x, int y) {
    add(up(x, y), up(x + 1, y));
    add(up(x, y) ^ 1, up(x + 1, y) ^ 1);
    add(left(x, y), left(x, y + 1));
    add(left(x, y) ^ 1, left(x, y + 1) ^ 1);
    add(up(x, y), left(x, y) ^ 1);
    add(up(x, y) ^ 1, left(x, y));
    add(up(x + 1, y), left(x, y) ^ 1);
    add(up(x + 1, y) ^ 1, left(x, y));
    add(up(x, y), left(x, y + 1) ^ 1);
    add(up(x, y) ^ 1, left(x, y + 1));
    add(up(x + 1, y), left(x, y + 1) ^ 1);
    add(up(x + 1, y) ^ 1, left(x, y + 1));
}

void solve() {
    cin >> n >> m;
    for (int i = 0; i < n * m << 2; i ++ ) p[i] = i;
    vector<vector<char>> mp(n, vector<char>(m));
    for (int i = 0; i < n; i ++ ) {
        for (int j = 0; j < m; j ++ ) {
            cin >> mp[i][j];
            if (mp[i][j] == 'A') addA(i, j);
            else addB(i, j);
        }
    }
    int ans = 0;
    unordered_map<int, int> st;
    for (int i = 0; i < n * m << 2; i ++ ) {
        if (find(i) == find(i ^ 1)) {
            return cout << "0\n", void();
        }
        if (!st.count(find(i))) ans ++ ;
        st[find(i)] = 1;
    }
    cout << qpow(2, ans >> 1) << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T = 1;
    cin >> T;
    while (T -- ) solve();
    return 0;
}
posted @ 2025-04-17 19:18  YipChip  阅读(18)  评论(0)    收藏  举报