QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#914508 | #10078. FS's Critical Concert | Screenwalkers (Hirotaka Yoneda, Masataka Yoneda, Daiki Kodama)# | AC ✓ | 2828ms | 37472kb | C++20 | 5.1kb | 2025-02-25 14:53:15 | 2025-02-25 14:53:15 |
Judging History
answer
#include <vector>
#include <cassert>
#include <iostream>
#include <algorithm>
using namespace std;
const int MOD = 998244353;
class modint {
private:
int x;
public:
modint() : x(0) {}
modint(long long x_) : x(x_ >= 0 ? x_ % MOD : (x_ + 1) % MOD + (MOD - 1)) {}
int val() const { return x; }
modint operator-() const { return modint(-x); }
modint& operator+=(const modint& m) { x = (x + m.x < MOD ? x + m.x : x + m.x - MOD); return *this; }
modint& operator-=(const modint& m) { x = (x >= m.x ? x - m.x : x - m.x + MOD); return *this; }
modint& operator*=(const modint& m) { x = 1LL * x * m.x % MOD; return *this; }
modint operator+(const modint& m) const { return modint(*this) += m; }
modint operator-(const modint& m) const { return modint(*this) -= m; }
modint operator*(const modint& m) const { return modint(*this) *= m; }
modint pow(long long b) const {
modint ans(1), a(*this);
while (b > 0) {
if (b & 1) {
ans *= a;
}
a *= a;
b >>= 1;
}
return ans;
}
modint inv() const { return pow(MOD - 2); }
};
namespace comber {
int N;
vector<modint> fact, factinv, Z;
void initialize(int N_) {
N = N_;
fact.resize(N + 1);
fact[0] = 1;
for (int i = 1; i <= N; i++) {
fact[i] = fact[i - 1] * i;
}
factinv.resize(N + 1);
factinv[N] = fact[N].inv();
for (int i = N; i >= 1; i--) {
factinv[i - 1] = factinv[i] * i;
}
Z.resize(N + 1);
for (int i = 0; i <= N; i++) {
Z[i] = modint(2).pow(1LL * i * (i - 1) / 2);
}
}
modint comb(int x, int y) {
assert(0 <= y && y <= x && x <= N);
return fact[x] * factinv[y] * factinv[x - y];
}
}
const modint base = 3;
vector<modint> ntt(vector<modint> v, int typ) {
modint root = (typ == 1 ? base : base.inv());
int size = v.size();
vector<modint> dat(size, 0);
for (int i = 0; i < size; i++) {
int r1 = 1, r2 = size / 2, cur = 0;
while (r2 >= 1) {
if ((i & r1) != 0) {
cur += r2;
}
r1 <<= 1;
r2 >>= 1;
}
dat[cur] = v[i];
}
for (int b = 2; b <= size; b *= 2) {
vector<modint> pows(b, 1);
pows[1] = root.pow((MOD - 1) / b);
for (int i = 2; i < b; i++) {
pows[i] = pows[i - 1] * pows[1];
}
for (int stt = 0; stt < size; stt += b) {
for (int i = 0; i < b / 2; i++) {
modint r1 = dat[stt + i] + pows[i + 0 * b / 2] * dat[stt + i + b / 2];
modint r2 = dat[stt + i] + pows[i + 1 * b / 2] * dat[stt + i + b / 2];
dat[stt + i + 0 * b / 2] = r1;
dat[stt + i + 1 * b / 2] = r2;
}
}
}
if (typ == 2) {
modint mult = modint(size).inv();
for (int i = 0; i < size; i++) {
dat[i] *= mult;
}
}
return dat;
}
vector<modint> convolve(vector<modint> a, vector<modint> b) {
int n = a.size(), m = b.size();
assert(n >= 1 && m >= 1);
if (min(n, m) <= 32) {
vector<modint> c(n + m - 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
c[i + j] += a[i] * b[j];
}
}
return c;
}
int size = 1 << (32 - __builtin_clz(n + m - 2));
a.resize(size);
b.resize(size);
a = ntt(a, 1);
b = ntt(b, 1);
for (int i = 0; i < size; i++) {
a[i] *= b[i];
}
a = ntt(a, 2);
a.resize(n + m - 1);
return a;
}
class online_convolution {
private:
int n;
vector<modint> a;
vector<modint> b;
vector<modint> c;
public:
online_convolution() : n(0), a(), b(), c() {}
modint add(modint sa, modint sb) {
n++;
a.push_back(sa);
b.push_back(sb);
c.push_back(modint(0));
if (n >= 2) {
c.push_back(modint(0));
}
int level = __builtin_ctz(~n) + 1;
if ((1 << level) > n) {
level--;
}
for (int i = 0; i < level; i++) {
vector<modint> suba1(a.begin() + (1 << i) - 1, a.begin() + (2 << i) - 1);
vector<modint> subb1(b.begin() + n - (1 << i), b.begin() + n);
vector<modint> subc1 = convolve(suba1, subb1);
for (int j = 0; j < (2 << i) - 1; j++) {
c[n - 1 + j] += subc1[j];
}
if (n != (2 << i) - 1) {
vector<modint> suba2(a.begin() + n - (1 << i), a.begin() + n);
vector<modint> subb2(b.begin() + (1 << i) - 1, b.begin() + (2 << i) - 1);
vector<modint> subc2 = convolve(suba2, subb2);
for (int j = 0; j < (2 << i) - 1; j++) {
c[n - 1 + j] += subc2[j];
}
}
}
return c[n - 1];
}
};
vector<modint> connected_graphs(int N) {
online_convolution conv;
vector<modint> C(N + 1);
C[1] = modint(1);
for (int i = 2; i <= N; i++) {
modint a = C[i - 1] * comber::factinv[i - 2];
modint b = comber::Z[i - 1] * comber::factinv[i - 1];
modint res = conv.add(a, b);
C[i] = comber::Z[i] - comber::fact[i - 1] * res;
}
return C;
}
modint solve(int N) {
if (N == 1) {
return modint(0);
}
vector<modint> C = connected_graphs(N);
vector<modint> A(N + 1);
for (int i = 1; i <= N; i++) {
A[i] = C[i] * comber::factinv[i - 1];
}
vector<modint> B = convolve(A, A);
modint ans = 0;
for (int i = 1; i <= N; i++) {
ans += B[i] * comber::fact[N - 2] * comber::factinv[N - i] * comber::Z[N - i];
}
return ans;
}
int main() {
int N;
cin >> N;
comber::initialize(N);
modint ans = solve(N);
cout << (ans * modint(1LL * N * (N - 1) / 2)).val() << endl;
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3584kb
input:
3
output:
9
result:
ok 1 number(s): "9"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
8
output:
130981312
result:
ok 1 number(s): "130981312"
Test #3:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
1
output:
0
result:
ok 1 number(s): "0"
Test #4:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
2
output:
1
result:
ok 1 number(s): "1"
Test #5:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
4
output:
96
result:
ok 1 number(s): "96"
Test #6:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
5
output:
1500
result:
ok 1 number(s): "1500"
Test #7:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
6
output:
37560
result:
ok 1 number(s): "37560"
Test #8:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
7
output:
1626912
result:
ok 1 number(s): "1626912"
Test #9:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
9
output:
591945260
result:
ok 1 number(s): "591945260"
Test #10:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
10
output:
877137661
result:
ok 1 number(s): "877137661"
Test #11:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
11
output:
654711510
result:
ok 1 number(s): "654711510"
Test #12:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
12
output:
896890421
result:
ok 1 number(s): "896890421"
Test #13:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
13
output:
544152239
result:
ok 1 number(s): "544152239"
Test #14:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
14
output:
203161729
result:
ok 1 number(s): "203161729"
Test #15:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
15
output:
686403302
result:
ok 1 number(s): "686403302"
Test #16:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
16
output:
551788068
result:
ok 1 number(s): "551788068"
Test #17:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
17
output:
778761614
result:
ok 1 number(s): "778761614"
Test #18:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
18
output:
372704747
result:
ok 1 number(s): "372704747"
Test #19:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
19
output:
48091879
result:
ok 1 number(s): "48091879"
Test #20:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
20
output:
811962966
result:
ok 1 number(s): "811962966"
Test #21:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
21
output:
580925653
result:
ok 1 number(s): "580925653"
Test #22:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
22
output:
473369147
result:
ok 1 number(s): "473369147"
Test #23:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
23
output:
370850086
result:
ok 1 number(s): "370850086"
Test #24:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
24
output:
633052748
result:
ok 1 number(s): "633052748"
Test #25:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
25
output:
760181773
result:
ok 1 number(s): "760181773"
Test #26:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
26
output:
618049730
result:
ok 1 number(s): "618049730"
Test #27:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
27
output:
197289938
result:
ok 1 number(s): "197289938"
Test #28:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
28
output:
708240707
result:
ok 1 number(s): "708240707"
Test #29:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
29
output:
726463024
result:
ok 1 number(s): "726463024"
Test #30:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
30
output:
587550457
result:
ok 1 number(s): "587550457"
Test #31:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
100
output:
721970458
result:
ok 1 number(s): "721970458"
Test #32:
score: 0
Accepted
time: 6ms
memory: 3840kb
input:
2562
output:
947609016
result:
ok 1 number(s): "947609016"
Test #33:
score: 0
Accepted
time: 9ms
memory: 3840kb
input:
3410
output:
462244613
result:
ok 1 number(s): "462244613"
Test #34:
score: 0
Accepted
time: 15ms
memory: 3904kb
input:
5712
output:
225049703
result:
ok 1 number(s): "225049703"
Test #35:
score: 0
Accepted
time: 32ms
memory: 4160kb
input:
10002
output:
577290168
result:
ok 1 number(s): "577290168"
Test #36:
score: 0
Accepted
time: 208ms
memory: 7152kb
input:
50012
output:
513616100
result:
ok 1 number(s): "513616100"
Test #37:
score: 0
Accepted
time: 337ms
memory: 10436kb
input:
75162
output:
197336463
result:
ok 1 number(s): "197336463"
Test #38:
score: 0
Accepted
time: 587ms
memory: 11784kb
input:
129257
output:
307374532
result:
ok 1 number(s): "307374532"
Test #39:
score: 0
Accepted
time: 1048ms
memory: 19136kb
input:
202572
output:
342782823
result:
ok 1 number(s): "342782823"
Test #40:
score: 0
Accepted
time: 1931ms
memory: 33276kb
input:
348252
output:
992752188
result:
ok 1 number(s): "992752188"
Test #41:
score: 0
Accepted
time: 2539ms
memory: 36152kb
input:
452632
output:
374752381
result:
ok 1 number(s): "374752381"
Test #42:
score: 0
Accepted
time: 2828ms
memory: 37472kb
input:
500000
output:
553811795
result:
ok 1 number(s): "553811795"