码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 724G: Xor-matic Number of the Graph

时间:2019-01-27 19:15:46      阅读:219      评论:0      收藏:0      [点我收藏+]

标签: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\) 取模的值。

题解:

比较简单的线性基和图结合的题目,需要用到线性基的一些基本性质。

对异或线性基在图上的应用稍有了解的同学很快可以发现结论:

  • 对于连通无向图 \(G=(V,E)\) 以及 \(G\) 的一棵生成树 \(T\)
  • \(G\) 中所有环(简单或非简单环)的异或和均可以被生成树中所有返祖边 \((x\to y)\) 对应的环 \((y\sim x\to y)\) 的异或和组成的线性基 \(B\) 表示出来。
  • \(u\) 到点 \(v\) 所有路径的异或和可以被 \(T\)\(u\)\(v\) 的路径的异或和异或上线性基 \(B\) 表示出来。
  • 更进一步地,\(T\)\(u\)\(v\) 的路径的异或和等于 \(u\) 到根的路径的异或和异或 \(v\) 到根的路径的异或和。
  • 所以 \(u\)\(v\) 所有路径的异或和等于 \(d_u\oplus d_v\oplus B\),其中 \(d_x\) 表示 \(x\) 到根的路径的异或和。

对于一对 \((u,v)\),尝试统计 \(d_u\oplus d_v\oplus B\) 中所有数的和。

直接做并不是很好做,考虑按位分开做:

  • 对于线性基 \(B\) 和二进制位 \(w\),有结论:
  • \(B\) 中元素个数为 \(S\),则 \(B\) 可以表示出 \(2^S\) 个不同的数。
  • 如果 \(B\) 中存在二进制第 \(w\) 位为 \(1\) 的数,则那 \(2^S\) 个数中恰有 \(2^{S-1}\) 个数的二进制第 \(w\) 位为 \(1\),另外 \(2^{S-1}\) 个数的二进制第 \(w\) 位为 \(0\)
  • 如果 \(B\) 中不存在二进制第 \(w\) 位为 \(1\) 的数,显然不可能表示出二进制第 \(w\) 位为 \(1\) 的数,全部 \(2^S\) 个数的二进制第 \(w\) 位均为 \(0\)
    可以通过组合恒等式 \(\sum_{i=0}^{n}\binom{n}{i}[i\bmod 2=1]=\begin{cases}0&,n=0\\2^{n-1}&,n>0\end{cases}\) 证明。

统计每一位有多少种能被表示出来的方式,统计进答案即可。

这样需要枚举 \((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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!