标签:bool ret 存在 ati 复杂度 联通 ase string sim
题目传送门:CF724G。
一张 \(n\) 个点的无向图,边有边权。
定义三元组 \((u,v,w)(1\le u\le v\le n)\) 合法当且仅当存在从点 \(u\) 到点 \(v\) 存在一条边权异或和为 \(w\) 的路径,经过多次的边需要算多次。
求所有合法三元组的 \(w\) 值之和对 \(10^9+7\) 取模的值。
比较简单的线性基和图结合的题目,需要用到线性基的一些基本性质。
对异或线性基在图上的应用稍有了解的同学很快可以发现结论:
对于一对 \((u,v)\),尝试统计 \(d_u\oplus d_v\oplus B\) 中所有数的和。
直接做并不是很好做,考虑按位分开做:
统计每一位有多少种能被表示出来的方式,统计进答案即可。
这样需要枚举 \((u,v)\),其实很简单就能优化。
直接枚举二进制位 \(w\),考虑线性基 \(B\) 中是否存在二进制第 \(w\) 位为 \(1\) 的数。
如果存在,这意味着无论 \(d_u,d_v\) 的二进制第 \(w\) 位是否为 \(1\),都恰有 \(2^{S-1}\) 条使得异或和的二进制第 \(w\) 位为 \(1\) 的路径。
这意味着 \(u,v\) 可以随便选,对答案的贡献为 \(2^w2^{S-1}\binom{n}{2}\)。
如果不存在,这意味着 \(d_u,d_v\) 的二进制第 \(w\) 位必须恰有一个为 \(1\),并且此时存在 \(2^S\) 条使得异或和的二进制第 \(w\) 位为 \(1\) 的路径。
这意味着 \(d_u,d_v\) 的第 \(w\) 位必须恰有一个为 \(1\),记第 \(w\) 位为 \(1\) 的 \(d_x\) 的个数为 \(x\),对答案的贡献为 \(2^w2^Sx(n-x)\)。
最后注意原图不一定联通,对于每个联通块分别计算即可。
时间复杂度 \(\mathrm{O}(n\log_2^2t_i)\)。
#include <cstdio>
#include <cstring>
typedef long long LL;
const int Mod = 1000000007;
const int Inv2 = 500000004;
const int MN = 100005;
const int MM = 400005;
int N, M;
int h[MN], nxt[MM], to[MM], tot; LL w[MM];
inline void ins(int x, int y, LL z) { nxt[++tot] = h[x], to[tot] = y, w[tot] = z, h[x] = tot; }
LL B[60], C;
inline void Add(LL x) {
for (int j = 59; ~j; --j) if (x >> j & 1)
if (!B[j]) { B[j] = x, C <<= 1; break; }
else x ^= B[j];
}
bool vis[MN];
LL d[MN];
int s[MN], t;
void DFS(int u, LL v) {
vis[u] = 1, d[u] = v, s[++t] = u;
for (int i = h[u]; i; i = nxt[i]) {
if (vis[to[i]]) Add(v ^ d[to[i]] ^ w[i]);
else DFS(to[i], v ^ w[i]);
}
}
LL Ans;
int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= M; ++i) {
int x, y; LL z;
scanf("%d%d%lld", &x, &y, &z);
ins(x, y, z); ins(y, x, z);
}
for (int i = 1; i <= N; ++i) if (!vis[i]) {
memset(B, 0, sizeof B), C = 1, t = 0;
DFS(i, 0);
C %= Mod;
for (int j = 0; j < 60; ++j) {
LL c = (1ll << j) % Mod;
bool ok = 0;
for (int k = 0; k < 60; ++k) if (B[k] >> j & 1) ok = 1;
if (ok) Ans = (Ans + (LL)t * (t - 1) / 2 % Mod * C % Mod * c) % Mod;
else {
int x = 0;
for (int i = 1; i <= t; ++i) if (d[s[i]] >> j & 1) ++x;
Ans = (Ans + 2ll * x * (t - x) % Mod * C % Mod * c) % Mod;
}
}
}
printf("%d\n", (LL)Ans * Inv2 % Mod);
return 0;
}
CodeForces 724G: Xor-matic Number of the Graph
标签:bool ret 存在 ati 复杂度 联通 ase string sim
原文地址:https://www.cnblogs.com/PinkRabbit/p/10326681.html