题解:ARC222E XOR Matching

赛时做法,和官解不太一样。

\(x\) 的出现次数为 \(c_x\)

不难推出

\[\begin{align*} f(0)&=\sum_{v=0}^{2^m-1}\left\lfloor\frac{c_v}{2}\right\rfloor\\ f(x)&=\sum_{v=0}^{2^m-1}[v<v\oplus x]\min(c_v,c_{v\oplus x})\ (x>0) \end{align*} \]

于是可以转化为求

\[\sum_{v=0}^{2^m-1}\left\lfloor\frac{c_v}{2}\right\rfloor+\sum_{i=0}^{2^m-1}\sum_{j=i+1}^{2^m-1}\min(c_i,c_j)10^{i\oplus j} \]

\(0\sim 2^m-1\) 内的数按 \(c_i\) 从大到小扫,设前面处理过的数集为 \(S\),那每次扫到一个数 \(x\) 的增量就是

\[c_x\sum_{y\in S}10^{x\oplus y} \]

于是问题转化为维护一个集合 \(S\),支持插入一个数、查询 \(\sum\limits_{y\in S}10^{x\oplus y}\)

折半成低 \(L\) 位和高 \(H\) 位,设 \(x=x_l+x_h2^L\)\(y=y_l+y_h2^L\),则

\[10^{x\oplus y}=10^{x_l\oplus y_l}\times 10^{(x_h\oplus y_h)2^L} \]

维护

\[f_{h,l}=\sum_{y\in S}[y_h=h]10^{l\oplus y_l} \]

那么对于一个固定的 \(x\),查询的答案就是

\[\sum_{h=0}^{2^H-1}10^{(x_h\oplus h)2^L}\times f_{h,x_l} \]

插入一个数 \(x\) 时,枚举 \(l=0\sim 2^L-1\),令 \(f_{x_h,l}\gets f_{x_h,l}+10^{l\oplus x_l}\) 即可。

对于每个 \(0\leq i<2^L\),预处理 \(10^i\),对于每个 \(0\leq i<2^H\),预处理 \(10^{i2^L}\)。时间复杂度为 \(\mathcal{O}(2^m+n2^{\lceil m/2\rceil})\)

代码
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using i128 = __int128;
using ui = unsigned int;
using ull = unsigned long long;
using u128 = unsigned __int128;
using ld = long double;
using pii = pair<int, int>;
const int MAXN = 2e5 + 5, MAXV = 1 << 20, MAXV2 = 1 << 10;
const int mod = 998244353;

template<typename T> T lowbit(T x) { return x & -x; }
template<typename T> void chkMin(T &x, T y) { x = y < x ? y : x; }
template<typename T> void chkMax(T &x, T y) { x = x < y ? y : x; }
template<typename T> T add(T x, T y) { return (x += y) >= mod ? x - mod : x; }
template<typename T> T sub(T x, T y) { return (x -= y) < 0 ? x + mod : x; }
template<typename T> void cadd(T &x, T y) { (x += y) >= mod ? (x -= mod) : x; }
template<typename T> void csub(T &x, T y) { (x -= y) < 0 ? (x += mod) : x; }

int n, m, ans, cnt[MAXV];
int pw1[MAXV2], pw2[MAXV2];
int f[MAXV2][MAXV2];

int qpow(int a, int b) {
	int res = 1;
	for (; b; b >>= 1) {
		if (b & 1) res = (ll)res * a % mod;
		a = (ll)a * a % mod;
	}
	return res;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		int x;
		cin >> x;
		++cnt[x];
	}
	int low = m + 1 >> 1, high = m - low;
	pw1[0] = 1;
	for (int i = 1; i < (1 << low); ++i) pw1[i] = (ull)pw1[i - 1] * 10 % mod;
	pw2[0] = 1;
	int mul = (ull)pw1[(1 << low) - 1] * 10 % mod;
	for (int i = 1; i < (1 << high); ++i) pw2[i] = (ull)pw2[i - 1] * mul % mod;
	vector<pii> vec;
	for (int i = 0; i < (1 << m); ++i) {
		if (!cnt[i]) continue;
		ans += cnt[i] >> 1;
		vec.emplace_back(cnt[i], i);
	}
	sort(vec.begin(), vec.end(), greater<>());
	for (auto [c, v] : vec) {
		int lowV = v & ((1 << low) - 1), highV = v >> low;
		int sum = 0;
		for (int h = 0; h < (1 << high); ++h)
			cadd<int>(sum, (ull)pw2[highV ^ h] * f[h][lowV] % mod);
		cadd<int>(ans, (ull)sum * c % mod);
		for (int l = 0; l < (1 << low); ++l)
			cadd(f[highV][l], pw1[lowV ^ l]);
	}
	cout << ans;
	return 0;
}
posted @ 2026-06-18 17:41  P2441M  阅读(8)  评论(0)    收藏  举报