QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#166238#6853. TravelPPPAC ✓6286ms55104kbC++177.1kb2023-09-06 03:20:172023-09-06 03:20:17

Judging History

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

  • [2023-09-06 03:20:17]
  • 评测
  • 测评结果:AC
  • 用时:6286ms
  • 内存:55104kb
  • [2023-09-06 03:20:17]
  • 提交

answer

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int mod = 998244353;

const int root = 31;

const int root_1 = 128805723;

const int root_pw = 1<<23;

int mult(int a, int b) {
    return (1LL * a * b) % mod;
}

int pw(int a, int b) {
    if (b == 0) return 1;
    if (b & 1) return mult(a, pw(a, b - 1));
    int res = pw(a, b / 2);
    return mult(res, res);
}

int sub(int a, int b) {
    int s = a - b;
    if (s < 0) s += mod;
    return s;
}

int sum(int a, int b) {
    int s = a + b;
    if (s >= mod) s -= mod;
    return s;
}

void fft (vector<int> & a, bool invert) {
    int n = (int) a.size();

    for (int i=1, j=0; i<n; ++i) {
        int bit = n >> 1;
        for (; j>=bit; bit>>=1)
            j -= bit;
        j += bit;
        if (i < j)
            swap (a[i], a[j]);
    }

    for (int len=2; len<=n; len<<=1) {
        int wlen = invert ? root_1 : root;
        for (int i=len; i<root_pw; i<<=1)
            wlen = int (wlen * 1ll * wlen % mod);
        for (int i=0; i<n; i+=len) {
            int w = 1;
            for (int j=0; j<len/2; ++j) {
                int u = a[i+j],  v = int (a[i+j+len/2] * 1ll * w % mod);
                a[i+j] = u+v < mod ? u+v : u+v-mod;
                a[i+j+len/2] = u-v >= 0 ? u-v : u-v+mod;
                w = int (w * 1ll * wlen % mod);
            }
        }
    }
    if (invert) {
        int nrev = pw(n, mod - 2);
        for (int i=0; i<n; ++i)
            a[i] = int (a[i] * 1ll * nrev % mod);
    }
}

void poly_mult(vector < int >& a, vector < int > b) {
    int s = a.size() + b.size();
    int r = 1;
    while (r < s) r *= 2;
    a.resize(r);
    b.resize(r);
    fft(a, false);
    fft(b, false);
    for (int j = 0; j < r; j++) {
        a[j] = mult(a[j], b[j]);
    }
    fft(a, true);
    while (!a.empty() && (a.back() == 0)) a.pop_back();
}
int k;
vector<int> convolution(vector<int>& A, vector<int>& B, vector<int> sz) {
    int T = 2 * A.size();
    int F = 1;
    while (F <= T) {
        F *= 2;
    }
    vector<vector<int>> P(k, vector<int>(F));
    vector<vector<int>> Q(k, vector<int>(F));
    vector<int> coef(sz.size());
    coef[0] = 1;
    for (int i = 1; i < sz.size(); i++) {
        coef[i] = coef[i - 1] * sz[i - 1] + 1;
        coef[i] %= k;
    }
    auto get_val = [&](int x) {
        int T = 0;
        for (int d = 0; d < sz.size(); d++) {
            T += coef[d] * (x % sz[d]);
            x /= sz[d];
        }
        T %= k;
        assert(x == 0);
        return T;
    };
    for (int i = 0; i < A.size(); i++) {
        P[get_val(i)][i] = A[i];
        Q[get_val(i)][i] = B[i];
    }
    for (int i = 0; i < k; i++) {
        fft(P[i], false);
        fft(Q[i], false);
    }
    vector<vector<int>> R(k, vector<int>(F));
    for (int a = 0; a < k; a++) {
        for (int b = 0; b < k; b++) {
            for (int c = 0; c < F; c++) {
                R[(a + b) % k][c] = sum(R[(a + b) % k][c], mult(P[a][c], Q[b][c]));
            }
        }
    }
    for (int c = 0; c < k; c++) {
        fft(R[c], true);
    }
    vector<int> ans(A.size());
    for (int z = 0; z < A.size(); z++) {
        ans[z] = R[get_val(z)][z];
    }
    return ans;
}
void solve() {
    cin >> k;
    vector<int> sz(k);
    int C = 1;
    for (int i = 0; i < k; i++) {
        cin >> sz[i];
        sz[i]++;
        C *= sz[i];
    }
    int n, m;
    vector<int> vals(C);
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        vector<int> y(k);
        for (int z = 0; z < k; z++) {
            cin >> y[z];
        }
        int D = 0;
        for (int z = k - 1; z >= 0; z--) {
            D *= sz[z];
            D += y[z];
        }
        vals[D] = sum(vals[D], 1);
    }
    assert(vals[0] == 0);
    for (int& i : vals) {
        i = sub(0, i);
    }
    vals[0] = 1;
    vector<vector<int>> P(m);
    for (int i = 0; i < m; i++) {
        vector<int> y(k);
        for (int z = 0; z < k; z++) {
            cin >> y[z];
        }
        P[i] = y;
    }
    sort(P.begin(), P.end());
    P.erase(unique(P.begin(), P.end()), P.end());
    if (!P.empty() && P[0] == vector<int>(k, 0)) {
        cout << 0 << '\n';
        return;
    }
    vector<int> lst(k);
    for (int i = 0; i < k; i++) lst[i] = sz[i] - 1;
    P.insert(P.begin(), vector<int>(k));
    if (!P.empty() && P.back() == lst) {
        cout << 0 << '\n';
        return;
    }
    P.emplace_back(lst);
    m = P.size();
    vector<int> cur_sz(k, 1);
    vector<int> state = {1};
    auto get_vec = [&](int x, vector<int>& sz) {
        vector<int> dig(sz.size());
        for (int i = 0; i < sz.size(); i++) {
            dig[i] = x % sz[i];
            x /= sz[i];
        }
        assert(x == 0);
        return dig;
    };
    auto get_num = [&](vector<int>& vec, vector<int>& sz) {
        int S = 0;
        for (int i = sz.size() - 1; i >= 0; i--) {
            S *= sz[i];
            S += vec[i];
            assert(vec[i] < sz[i]);
        }
        return S;
    };
    while (true) {
        int id = -1;
        for (int p = 0; p < k; p++) {
            if (cur_sz[p] < sz[p]) {
                id = p;
                break;
            }
        }
        if (id == -1) break;
        int new_sz = min(cur_sz[id] << 1, sz[id]);
        vector<int> new_cur = cur_sz;
        new_cur[id] = new_sz;
        int prod = 1;
        for (int u : new_cur) prod *= u;
        int prv_prod = 1;
        vector<int> state_P(prod);
        vector<int> new_state(prod);
        for (int i = 0; i < prod; i++) {
            auto dig = get_vec(i, new_cur);
            state_P[i] = vals[get_num(dig, sz)];
        }
        for (int i = 0; i < state.size(); i++) {
            auto dig = get_vec(i, cur_sz);
            new_state[get_num(dig, new_cur)] = state[i];
        }
        state_P = convolution(state_P, new_state, new_cur);
        state_P = convolution(state_P, new_state, new_cur);
        for (int i = 0; i < new_state.size(); i++) {
            new_state[i] = sub(mult(2, new_state[i]), state_P[i]);
        }
        swap(state, new_state);
        swap(new_cur, cur_sz);
    };
    vector<int> dp(m);
    dp[0] = 1;
    for (int i = 1; i < m; i++) {
        for (int j = 0; j < i; j++) {
            vector<int> dif(k);
            bool ok = true;
            for (int z = 0; z < k; z++) {
                dif[z] = P[i][z] - P[j][z];
                if (dif[z] < 0) {
                    ok = false;
                    break;
                }
            }
            if (ok) {
                int coef = state[get_num(dif, sz)];
                if (j != 0) coef = sub(0, coef);
                dp[i] = sum(dp[i], mult(dp[j], coef));
            }
        }
    }
    cout << dp.back() << '\n';
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
#ifdef DEBUG
    freopen("input.txt", "r", stdin);
#endif
    int tst;
    cin >> tst;
    while (tst--) solve();
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 6286ms
memory: 55104kb

input:

5
2
100 1000
100000 1000
1 0
0 1
50 325
24 569
67 955
65 249
4 703
84 894
49 694
24 563
20 548
66 537
9 867
46 538
1 224
9 318
70 699
51 843
12 122
96 965
44 494
19 978
30 293
23 526
76 636
19 922
47 38
30 499
43 143
14 376
56 426
35 256
47 994
81 440
24 557
79 80
59 823
12 326
23 90
74 231
51 313
8...

output:

229928183
629684811
165005598
406354790
570309629

result:

ok 5 lines