QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#360911#8173. T Tile Placement Countingucup-team1198AC ✓683ms6940kbC++147.7kb2024-03-22 15:27:512024-03-22 15:27:52

Judging History

你现在查看的是最新测评结果

  • [2024-03-22 15:27:52]
  • 评测
  • 测评结果:AC
  • 用时:683ms
  • 内存:6940kb
  • [2024-03-22 15:27:51]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

const int MOD = 998244353;

int add(int a, int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}

int sub(int a, int b) {
    return a >= b ? a - b : a + MOD - b;
}

int mul(int a, int b) {
    return (1ll * a * b) % MOD;
}

int pw(int x, int n) {
    int res = 1;
    while (n) {
        if (n % 2 == 0) {
            x = mul(x, x);
            n /= 2;
        } else {
            res = mul(res, x);
            --n;
        }
    }
    return res;
}

const int MAXN = 7;
vector<int> g[MAXN * 4];

void clear_g(int n) {
    for (int i = 0; i < 2 * n; ++i) {
        g[i].clear();
    }
}

void add_start(const string& s) {
    int n = s.size();
    vector<int> st;
    for (int i = 0; i < n; ++i) {
        if (s[i] == '(') {
            st.push_back(i);
        } else {
            g[st.back()].push_back(i);
            g[i].push_back(st.back());
            st.pop_back();
        }
    }
}

void add_square(int n, int i, int c) {
    if (c == 0) {
        g[i].push_back(i + 1);
        g[i + 1].push_back(i);
        g[i + n].push_back(i + 1 + n);
        g[i + 1 + n].push_back(i + n);
    } else {
        g[i].push_back(i + n);
        g[i + n].push_back(i);
        g[i + 1].push_back(i + 1 + n);
        g[i + 1 + n].push_back(i + 1);
    }
}

pair<string, int> get(int n) {
    vector<int> used(2 * n);
    string s;
    for (int i = n; i < 2 * n; ++i) {
        if (used[i]) {
            s.push_back(')');
            continue;
        }
        s.push_back('(');
        int j = i;
        while (j != -1) {
            used[j] = 1;
            int nj = -1;
            for (int j1 : g[j]) {
                if (!used[j1]) {
                    nj = j1;
                    break;
                }
            }
            j = nj;
        }
    }
    int cnt = 1;
    for (int i = 0; i < n; ++i) {
        if (used[i]) {
            continue;
        }
        int j = i;
        while (j != -1) {
            used[j] = 1;
            int nj = -1;
            for (int j1 : g[j]) {
                if (!used[j1]) {
                    nj = j1;
                    break;
                }
            }
            j = nj;
        }
        cnt *= 2;
    }
    return {s, cnt};
}

vector<string> all;

void gen(string cur, int bal, int n) {
    if ((int)cur.size() == n) {
        if (bal == 0) {
            all.push_back(cur);
        }
        return;
    }
    if (bal > 0) {
        cur.push_back(')');
        gen(cur, bal - 1, n);
        cur.pop_back();
    }
    if (bal + 1 <= n - (int)cur.size() - 1) {
        cur.push_back('(');
        gen(cur, bal + 1, n);
        cur.pop_back();
    }
}

vector<vector<int>> operator*(const vector<vector<int>>& a, const vector<vector<int>>& b) {
    int n = a.size();
    int m = a[0].size();
    int k = b[0].size();
    vector<vector<int>> c(n, vector<int>(k, 0));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < k; ++j) {
            for (int p = 0; p < m; ++p) {
                c[i][j] = add(c[i][j], mul(a[i][p], b[p][j]));
            }
        }
    }
    return c;
}

vector<int> operator*(const vector<int>& a, const vector<int>& b) {
    vector<int> c(a.size() + b.size() - 1);
    for (int i = 0; i < (int)a.size(); ++i) {
        for (int j = 0; j < (int)b.size(); ++j) {
            c[i + j] = add(c[i + j], mul(a[i], b[j]));
        }
    }
    return c;
}

void cut(vector<int>& a, const vector<int>& p) {
    int n = p.size();
    while (a.size() > p.size()) {
        for (int i = 0; i < n; ++i) {
            a[a.size() - n - 1 + i] = add(a[a.size() - n - 1 + i], mul(a.back(), p[i]));
        }
        a.pop_back();
    }
}

vector<int> binpow(vector<int> x, int64_t m, const vector<int>& p) {
    vector<int> res = {1};
    while (m) {
        if (m % 2 == 0) {
            x = x * x;
            cut(x, p);
            m /= 2;
        } else {
            res = res * x;
            cut(res, p);
            --m;
        }
    }
    return res;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int h;
    int64_t w;
    cin >> h >> w;
    if (h % 4 != 0 || w % 4 != 0) {
        cout << "0\n";
        return 0;
    }

    h /= 2; w /= 2;
    gen("", 0, h);
    map<string, int> id;
    int C = all.size();
    for (int i = 0; i < C; ++i) {
        id[all[i]] = i;
    }

    vector<vector<int>> s(C, vector<int>(1, 0));
    vector<vector<int>> PtB(C, vector<int>(C, 0));
    vector<vector<int>> BtP(C, vector<int>(C, 0));
    vector<vector<int>> t(1, vector<int>(C, 0));

    s[0][0] = 1;
    for (int i = 0; i < C; ++i) {
        clear_g(h);
        add_start(all[i]);
        for (int j = 0; j < h; j += 2) {
            add_square(h, j, 0);
        }
        auto res = get(h);
        t[0][i] = res.second;
    }

    for (int i = 0; i < C; ++i) {
        for (int mask = 0; mask < (1 << (h / 2)); ++mask) {
            clear_g(h);
            add_start(all[i]);
            for (int j = 0; j < h; j += 2) {
                if (mask & (1 << (j / 2))) {
                    add_square(h, j, 1);
                } else {
                    add_square(h, j, 0);
                }
            }
            auto res = get(h);
            BtP[id[res.first]][i] = add(BtP[id[res.first]][i], res.second);
        }
    }

    for (int i = 0; i < C; ++i) {
        for (int mask = 0; mask < (1 << (h / 2 - 1)); ++mask) {
            clear_g(h);
            add_start(all[i]);
            g[0].push_back(h);
            g[h].push_back(0);
            g[h - 1].push_back(2 * h - 1);
            g[2 * h - 1].push_back(h - 1);
            for (int j = 1; j + 1 < h; j += 2) {
                if (mask & (1 << (j / 2))) {
                    add_square(h, j, 1);
                } else {
                    add_square(h, j, 0);
                }
            }
            auto res = get(h);
            /// cerr << all[i] << "->" << res.first << " " << res.second << endl;
            PtB[id[res.first]][i] = add(PtB[id[res.first]][i], res.second);
        }
    }

    t = t * PtB;
    vector<vector<int>> A = BtP * PtB;
    int64_t m = w / 2 - 1;
    /// t*A^m*s

    vector<int> val(2 * C);
    for (int i = 0; i < 2 * C; ++i) {
        val[i] = (t * s)[0][0];
        s = A * s;
    }

    vector<vector<int>> eq(C, vector<int>(C + 1, 0));
    for (int i = 0; i < C; ++i) {
        for (int k = 0; k <= C; ++k) {
            eq[i][k] = val[i + k];
        }
    }
    int col = 0;
    vector<array<int, 2>> var;
    for (int i = 0; i < C && col < C; ++i) {
        int id = -1;
        for (int j = i; j < C; ++j) {
            if (eq[j][i] != 0) {
                id = j;
                break;
            }
        }
        if (id == -1) {
            ++col;
            --i;
            continue;
        }
        swap(eq[i], eq[id]);
        var.push_back({col, i});
        int anti = pw(eq[i][i], MOD - 2);
        for (int j = 0; j <= C; ++j) {
            eq[i][j] = mul(eq[i][j], anti);
        }
        for (int j = 0; j < C; ++j) {
            if (j == i) continue;
            int val = eq[j][i];
            for (int k = 0; k <= C; ++k) {
                eq[j][k] = sub(eq[j][k], mul(val, eq[i][k]));
            }
        }
        ++col;
    }
    vector<int> p(C);
    for (auto elem : var) {
        p[elem[0]] = eq[elem[1]][C];
    }

    vector<int> x = {0, 1};
    x = binpow(x, m, p);
    int ans = 0;
    for (int i = 0; i < C; ++i) {
        ans = add(ans, mul(x[i], val[i]));
    }
    cout << ans << "\n";

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3612kb

input:

4 4

output:

2

result:

ok "2"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3664kb

input:

2 8

output:

0

result:

ok "0"

Test #3:

score: 0
Accepted
time: 0ms
memory: 3704kb

input:

12 3456

output:

491051233

result:

ok "491051233"

Test #4:

score: 0
Accepted
time: 0ms
memory: 3672kb

input:

1 1

output:

0

result:

ok "0"

Test #5:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

20 999999999999999983

output:

0

result:

ok "0"

Test #6:

score: 0
Accepted
time: 0ms
memory: 3908kb

input:

24 999999999999999994

output:

0

result:

ok "0"

Test #7:

score: 0
Accepted
time: 0ms
memory: 3836kb

input:

24 999999999999999955

output:

0

result:

ok "0"

Test #8:

score: 0
Accepted
time: 675ms
memory: 6648kb

input:

28 999999999999999928

output:

846645622

result:

ok "846645622"

Test #9:

score: 0
Accepted
time: 0ms
memory: 3616kb

input:

28 999999999999999971

output:

0

result:

ok "0"

Test #10:

score: 0
Accepted
time: 0ms
memory: 3672kb

input:

28 999999999999999901

output:

0

result:

ok "0"

Test #11:

score: 0
Accepted
time: 0ms
memory: 3616kb

input:

28 999999999999999945

output:

0

result:

ok "0"

Test #12:

score: 0
Accepted
time: 0ms
memory: 3672kb

input:

30 1000000000000000000

output:

0

result:

ok "0"

Test #13:

score: 0
Accepted
time: 0ms
memory: 3840kb

input:

4 144115188075855868

output:

479168365

result:

ok "479168365"

Test #14:

score: 0
Accepted
time: 0ms
memory: 3668kb

input:

4 288230376151711740

output:

661413713

result:

ok "661413713"

Test #15:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

4 576460752303423484

output:

854857972

result:

ok "854857972"

Test #16:

score: 0
Accepted
time: 0ms
memory: 3904kb

input:

8 144115188075855868

output:

266363233

result:

ok "266363233"

Test #17:

score: 0
Accepted
time: 0ms
memory: 3664kb

input:

8 288230376151711740

output:

862901307

result:

ok "862901307"

Test #18:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

8 576460752303423484

output:

455991900

result:

ok "455991900"

Test #19:

score: 0
Accepted
time: 0ms
memory: 3672kb

input:

12 144115188075855868

output:

226857121

result:

ok "226857121"

Test #20:

score: 0
Accepted
time: 0ms
memory: 3904kb

input:

12 288230376151711740

output:

717445399

result:

ok "717445399"

Test #21:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

12 576460752303423484

output:

935277864

result:

ok "935277864"

Test #22:

score: 0
Accepted
time: 1ms
memory: 3692kb

input:

16 144115188075855868

output:

631950327

result:

ok "631950327"

Test #23:

score: 0
Accepted
time: 1ms
memory: 3680kb

input:

16 288230376151711740

output:

73767413

result:

ok "73767413"

Test #24:

score: 0
Accepted
time: 1ms
memory: 3676kb

input:

16 576460752303423484

output:

329402693

result:

ok "329402693"

Test #25:

score: 0
Accepted
time: 2ms
memory: 3728kb

input:

20 144115188075855868

output:

125405814

result:

ok "125405814"

Test #26:

score: 0
Accepted
time: 2ms
memory: 3924kb

input:

20 288230376151711740

output:

794579293

result:

ok "794579293"

Test #27:

score: 0
Accepted
time: 0ms
memory: 3960kb

input:

20 576460752303423484

output:

726571847

result:

ok "726571847"

Test #28:

score: 0
Accepted
time: 27ms
memory: 4200kb

input:

24 144115188075855868

output:

310529292

result:

ok "310529292"

Test #29:

score: 0
Accepted
time: 28ms
memory: 3996kb

input:

24 288230376151711740

output:

493789216

result:

ok "493789216"

Test #30:

score: 0
Accepted
time: 25ms
memory: 3984kb

input:

24 576460752303423484

output:

606221157

result:

ok "606221157"

Test #31:

score: 0
Accepted
time: 682ms
memory: 6940kb

input:

28 144115188075855868

output:

964541053

result:

ok "964541053"

Test #32:

score: 0
Accepted
time: 679ms
memory: 6868kb

input:

28 288230376151711740

output:

42971353

result:

ok "42971353"

Test #33:

score: 0
Accepted
time: 683ms
memory: 6736kb

input:

28 576460752303423484

output:

179569141

result:

ok "179569141"

Test #34:

score: 0
Accepted
time: 0ms
memory: 3648kb

input:

6 5

output:

0

result:

ok "0"

Test #35:

score: 0
Accepted
time: 0ms
memory: 3560kb

input:

14 28

output:

0

result:

ok "0"

Test #36:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

25 6365

output:

0

result:

ok "0"

Test #37:

score: 0
Accepted
time: 0ms
memory: 3876kb

input:

18 529543996

output:

0

result:

ok "0"

Test #38:

score: 0
Accepted
time: 1ms
memory: 3608kb

input:

10 675199829716849556

output:

0

result:

ok "0"

Test #39:

score: 0
Accepted
time: 2ms
memory: 3720kb

input:

20 425279816112802872

output:

269059955

result:

ok "269059955"

Test #40:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

8 38212554426330756

output:

207344318

result:

ok "207344318"

Test #41:

score: 0
Accepted
time: 26ms
memory: 3936kb

input:

24 666881067086698696

output:

245351821

result:

ok "245351821"

Test #42:

score: 0
Accepted
time: 0ms
memory: 3640kb

input:

4 728683474913510792

output:

466882081

result:

ok "466882081"

Test #43:

score: 0
Accepted
time: 672ms
memory: 6704kb

input:

28 201838304882525604

output:

217184228

result:

ok "217184228"

Test #44:

score: 0
Accepted
time: 0ms
memory: 3668kb

input:

4 8560

output:

596875387

result:

ok "596875387"

Test #45:

score: 0
Accepted
time: 0ms
memory: 3644kb

input:

12 60764

output:

930662011

result:

ok "930662011"

Test #46:

score: 0
Accepted
time: 0ms
memory: 3904kb

input:

8 45272

output:

239612337

result:

ok "239612337"

Test #47:

score: 0
Accepted
time: 0ms
memory: 3672kb

input:

8 84616

output:

826857610

result:

ok "826857610"

Test #48:

score: 0
Accepted
time: 0ms
memory: 3640kb

input:

4 316408

output:

529567983

result:

ok "529567983"

Test #49:

score: 0
Accepted
time: 0ms
memory: 3912kb

input:

8 12

output:

1182

result:

ok "1182"

Test #50:

score: 0
Accepted
time: 0ms
memory: 3872kb

input:

8 16

output:

16644

result:

ok "16644"

Test #51:

score: 0
Accepted
time: 0ms
memory: 3904kb

input:

4 8

output:

6

result:

ok "6"

Test #52:

score: 0
Accepted
time: 0ms
memory: 3656kb

input:

12 16

output:

5253822

result:

ok "5253822"

Extra Test:

score: 0
Extra Test Passed