QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#914508#10078. FS's Critical ConcertScreenwalkers (Hirotaka Yoneda, Masataka Yoneda, Daiki Kodama)#AC ✓2828ms37472kbC++205.1kb2025-02-25 14:53:152025-02-25 14:53:15

Judging History

This is the latest submission verdict.

  • [2025-02-25 14:53:15]
  • Judged
  • Verdict: AC
  • Time: 2828ms
  • Memory: 37472kb
  • [2025-02-25 14:53:15]
  • Submitted

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"