CF241B 题解
Un1quAIoid · · 题解
P5283 [十二省联考 2019] 异或粽子 加强版。
step1
首先先将
把所有
这个可以从高位到低位按位确定。假设当前考虑完了
由于 Trie 上每个结点只会被遍历一遍,这部分复杂度是
step2
接下来考虑统计答案,这里只统计异或和小于
枚举点对异或和和第
step3
最后来分析复杂度:
首先是
然后是暴力拆位算贡献的部分,每一对
总复杂度
代码(写的很丑QwQ):
#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define rep for (int t = 2; t--; )
using namespace std;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline int read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
typedef long long ll;
const int N = 5e4+5;
const int Mod = 1e9+7;
int n, a[N], tot = 1, ans;
ll m, lim;
int bf[N * 2][2][30], c, (*s[N * 30])[30];
int cor[N * 30];
vector<int> id[31];
inline void Add(int &a, int b) { a += b; if (a >= Mod) a -= Mod; }
struct node {
int son[2], siz, d;
} T[N * 30];
#define son(p, s) T[p].son[s]
inline void ins(int v) {
int p = 1;
for (int i = 29; ~i; i--) {
int g = v >> i & 1;
if (son(p, g)) p = son(p, g);
else p = son(p, g) = ++tot, T[p].d = i, id[i].pb(p);
T[p].siz++;
}
if (T[p].siz == 1) s[p] = bf[c++];
}
int main() {
n = read(), m = read() * 2ll; T[1].d = 30;
for (int i = 1; i <= n; i++) ins(read());
for (int i = tot; i; i--) {
rep if (son(i, t)) s[son(i, t)][t][T[son(i, t)].d] += T[son(i, t)].siz;
if (son(i, 0) && son(i, 1)) {
s[i] = bf[c++];
for (int k = T[i].d - 1; ~k; k--)
rep s[i][t][k] = s[son(i, 0)][t][k] + s[son(i, 1)][t][k];
} else if (son(i, 0) | son(i, 1)) s[i] = s[son(i, 0) | son(i, 1)];
}
id[30].pb(1); cor[1] = 1;
for (int b = 29; ~b; b--) {
ll cnt = 0;
for (int i : id[b + 1]) if (cor[i])
rep cnt += T[son(i, t)].siz * T[son(cor[i], t ^ 1)].siz;
if (cnt >= m) {//这一位为1
lim |= 1 << b;
for (int i : id[b + 1])
rep cor[son(i, t)] = son(cor[i], t ^ 1);
} else {//这一位为0
m -= cnt;
for (int i : id[b + 1])
rep {
cor[son(i, t)] = son(cor[i], t);
int x = son(cor[i], t ^ 1), y = son(i, t);
if (x && y) {
Add(ans, lim * T[x].siz * T[y].siz % Mod);
for (int k = b; ~k; k--)
rep Add(ans, (1ll << k) * s[x][t][k] * s[y][t ^ 1][k] % Mod);
}
}
}
}
Add(ans, lim * m % Mod);
printf("%lld", (ll) ans * (Mod + 1) / 2 % Mod);
return 0;
}