CF1930E 2..3...4.... Wonderful! Wonderful! 题解

Description

Stack has an array $ a $ of length $ n $ such that $ a_i = i $ for all $ i $ ( $ 1 \leq i \leq n $ ). He will select a positive integer $ k $ ( $ 1 \leq k \leq \lfloor \frac{n-1}{2} \rfloor $ ) and do the following operation on $ a $ any number (possibly $ 0 $ ) of times.

  • Select a subsequence $ ^\dagger $ $ s $ of length $ 2 \cdot k + 1 $ from $ a $ . Now, he will delete the first $ k $ elements of $ s $ from $ a $ . To keep things perfectly balanced (as all things should be), he will also delete the last $ k $ elements of $ s $ from $ a $ .

Stack wonders how many arrays $ a $ can he end up with for each $ k $ ( $ 1 \leq k \leq \lfloor \frac{n-1}{2} \rfloor $ ). As Stack is weak at counting problems, he needs your help.

Since the number of arrays might be too large, please print it modulo $ 998,244,353 $ .

$ ^\dagger $ A sequence $ x $ is a subsequence of a sequence $ y $ if $ x $ can be obtained from $ y $ by deleting several (possibly, zero or all) elements. For example, $ [1, 3] $ , $ [1, 2, 3] $ and $ [2, 3] $ are subsequences of $ [1, 2, 3] $ . On the other hand, $ [3, 1] $ and $ [2, 1, 3] $ are not subsequences of $ [1, 2, 3] $ .

3n1063\leq n\leq 10^6 .

Solution

不妨设 xx 为总共删的数的个数,pip_i 表示 ii 是否被删,考虑什么样的序列是合法的。

  1. x=2kx=2k,则充要条件为存在 ii 使得 pi=0p_i=0ii 之前和之后都有恰好 kk11

  2. x>2kx>2k,则如果不存在一个 ii 使得 pi=0p_i=0ii 之前和之后都有至少 kk11,那么最后一步一定不合法。如果一定存在,那么可以先把左右两边的 11 的个数删成 [k,3k)[k,3k) 然后就必然合法。

所以一个序列合法的条件为存在一个 ii 使得 pi=0p_i=0ii 之前和之后都有至少 kk11

考虑用总数减去不合法的方案数,先把 2x2x11 插进去,然后每个 00 只能插入左右各 kk 个空,总方案数即为:

(nx)(nx+2k12k1)\binom{n}{x}-\binom{n-x+2k-1}{2k-1}

时间复杂度:O(nlogn)O(n\log n)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 1e6 + 5, kMod = 998244353;

int n;
int fac[kMaxN], ifac[kMaxN], inv[kMaxN];

constexpr int qpow(int bs, int64_t idx = kMod - 2) {
int ret = 1;
for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod)
if (idx & 1)
ret = (int64_t)ret * bs % kMod;
return ret;
}

inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }

int C(int m, int n) {
if (m < n || m < 0 || n < 0) return 0;
return 1ll * fac[m] * ifac[n] % kMod * ifac[m - n] % kMod;
}

void prework() {
fac[0] = ifac[0] = fac[1] = ifac[1] = inv[1] = 1;
for (int i = 2; i <= 1e6; ++i) {
inv[i] = 1ll * (kMod - kMod / i) * inv[kMod % i] % kMod;
fac[i] = 1ll * i * fac[i - 1] % kMod;
ifac[i] = 1ll * inv[i] * ifac[i - 1] % kMod;
}
}

int solve(int n, int k) {
int ret = 1;
for (int i = 2 * k; i <= n; i += 2 * k) {
inc(ret, sub(C(n, i), C(n - i + 2 * k - 1, 2 * k - 1)));
}
return ret;
}

void dickdreamer() {
std::cin >> n;
for (int i = 1; i <= (n - 1) / 2; ++i)
std::cout << solve(n, i) << ' ';
std::cout << '\n';
}

int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
std::cin >> T;
prework();
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

CF1930E 2..3...4.... Wonderful! Wonderful! 题解
https://sobaliuziao.github.io/2024/02/25/post/3a6aa1d7.html
作者
Egg_laying_master
发布于
2024年2月25日
许可协议