QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#166238 | #6853. Travel | PPP | AC ✓ | 6286ms | 55104kb | C++17 | 7.1kb | 2023-09-06 03:20:17 | 2023-09-06 03:20:17 |
Judging History
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