Public Round #14 A 安顿 题解

Description

对于一个数组 AA 和数字 XX,让我们定义 f(A,X)f(A,X) 如下:

如果不能将 AA 拆分为几个子段使得每个子数组中所有元素的异或不等于 XX,则 f(A,X)=0f(A,X)=0

否则,f(A,X)f(A,X) 等于这种拆分中最大可能的子段数。

给定整数 N,KN,KXX,其中 0X<2K0\leq X<2^K。 考虑长度为 NN 的数组 AA,如果每个元素都是从 002K12^K-1 均匀生成的整数。 求 f(A,X)f(A,X) 的期望值对 998244353998244353 取模的值。

1N106,1K60,0X<2K1 \le N \le 10^6, 1 \le K \le 60, 0 \leq X < 2^K

Solution

考虑将 AA 的前缀异或和数组 SS 拿出来,题目转化为选出最多的断点,满足 i0=0<i1<i2<<ik=ni_0=0<i_1<i_2<\ldots<i_k=n,且 SijSij1XS_{i_j}\oplus S_{i_{j-1}}\neq X

首先如果 X=0X=0,那么显然 f(A,X)f(A,X) 等于 SS 中极长连续段的个数减一。

如果 X0X\neq 0,考虑用类似 X=0X=0 的做法,将 vvvXv\oplus X 看成一种数去缩连续段,那么不同连续段之间显然不互相影响。而对于连续段内,如果当前是开始或者末尾连续段,个数即为开始或者末尾对应的数的个数,否则个数为这个连续段内两种数的出现次数最大值。容易发现这么做是最优的。

然后考虑怎么计数。

fif_i 表示长度为 ii 的连续段(不在开始或者末尾)的贡献。可以得到:

fi=j=0i(ij)max{j,ij}f_i=\sum_{j=0}^{i}{\binom{i}{j}\max\{j,i-j\}}

这个东西可以分类讨论 max{j,ij}\max\{j,i-j\} 的类型然后递推求。

对于前缀和后缀串的贡献容易得到。

时间复杂度:O(n)O(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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <bits/stdc++.h>

#define int int64_t

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

int n, k, x, cnt;
int fac[kMaxN], ifac[kMaxN], f[kMaxN], g[kMaxN];

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 fix(int x) { return (x % kMod + kMod) % kMod; }
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; }
inline int getop(int x) { return (~x & 1) ? 1 : (kMod - 1); }

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(int n = 1e6) {
fac[0] = 1;
for (int i = 1; i <= n; ++i) fac[i] = 1ll * i * fac[i - 1] % kMod;
ifac[n] = qpow(fac[n]);
for (int i = n; i; --i) ifac[i - 1] = 1ll * i * ifac[i] % kMod;
}

int getcnt(int n) {
if (n == 0) return 0;
else if (n == 1) return 1;
else return add(1ll * (n - 1) * qpow(2, n - 2) % kMod, qpow(2, n - 1));
}

void dickdreamer() {
std::cin >> n >> k >> x;
prework();
int ans = 0, cnt = fix(1ll << k), cntg = fix(1ll << (k - 1));
if (x == 0) return void(std::cout << sub(n, 1ll * n * qpow(cnt) % kMod) << '\n');
for (int i = 2; i <= n; ++i) {
g[i] = add(2ll * g[i - 1] % kMod, 1ll * getop(i) * C(i - 2, i / 2 - 1) % kMod);
}
for (int i = 1; i <= n; ++i) {
f[i] = sub(2ll * i % kMod * g[i] % kMod, (i % 2 == 0) * (i / 2) * C(i, i / 2) % kMod);
f[i] = sub(1ll * i * qpow(2, i) % kMod, f[i]);
if (i <= n - 2) inc(ans, 1ll * (n - i - 1) * f[i] % kMod * cntg % kMod * (cnt - 2) % kMod * (cnt - 2) % kMod * qpow(cnt, n - i - 2) % kMod);
}
// std::cerr << f[4] << '\n';
for (int i = 1; i <= n - 1; ++i)
inc(ans, 1ll * f[i] * (cntg - 1) % kMod * (cnt - 2) % kMod * qpow(cnt, n - i - 1) % kMod);
// std::cerr << ans << '\n';
for (int i = 1; i <= n - 1; ++i) { // 后缀
inc(ans, 1ll * getcnt(i) * cnt % kMod * (cnt - 2) % kMod * qpow(cnt, n - i - 1) % kMod);
}
// std::cerr << ans << '\n';
inc(ans, 1ll * getcnt(n) % kMod * (cnt - 2) % kMod);
// std::cerr << ans << '\n';
// std::cerr << 124780545ll * 16 % kMod << '\n';
for (int i = 1; i <= n - 1; ++i) {
inc(ans, 1ll * i * qpow(2, i - 1) % kMod * (cnt - 2) % kMod * qpow(cnt, n - i - 1) % kMod);
}
// std::cerr << ans << '\n';
for (int i = 1; i <= n; ++i) inc(ans, 1ll * i * C(n - 1, i - 1) % kMod);
// std::cerr << ans << '\n';
std::cout << 1ll * ans * qpow(qpow(cnt), n) % kMod << '\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;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

Public Round #14 A 安顿 题解
https://sobaliuziao.github.io/2025/02/06/post/5e5a7484.html
作者
Egg_laying_master
发布于
2025年2月6日
许可协议