zoukankan      html  css  js  c++  java
  • CF 724 G. Xor-matic Number of the Graph

    G. Xor-matic Number of the Graph

    链接

    题意:

      给定一个无向图,一个interesting的三元环(u,v,s)满足,从u到v的路径上的异或和等于s,三元环的权值为s,求所有三元环权值之和。

    分析:

      求出所有的三元环,建立线性基,然后逐位求每一位的贡献。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline LL read() {
        LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 100005, mod = 1e9 + 7;
    struct Edge{ int to, nxt; LL w; } e[500005];
    int head[N], En;
    LL dis[N], b[65], mi[N], Ans;
    bool vis[N];
    vector<LL> B;
    vector<int> A;
    
    inline void add_edge() {
        int u = read(), v = read(); LL w = read();
        ++En; e[En].to = v, e[En].w = w; e[En].nxt = head[u]; head[u] = En;
        ++En; e[En].to = u, e[En].w = w; e[En].nxt = head[v]; head[v] = En;
    }
    void dfs(int u) {
        A.push_back(u);
        vis[u] = 1;
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (vis[v]) B.push_back(dis[u] ^ e[i].w ^ dis[v]);
            else {
                dis[v] = dis[u] ^ e[i].w;
                dfs(v);
            }
        }
    }
    void Insert(LL x) {
        for (int i = 60; ~i; --i) {
            if ((x >> i) & 1) {
                if (b[i]) x ^= b[i]; 
                else {
                    b[i] = x; 
                    break; 
                }
            }
        }
    }
    void Clear() {
        memset(b, 0, sizeof(b));
        A.clear(), B.clear();
    }
    inline void mul(LL &x,LL y) { x *= y; x %= mod; }
    inline void add(LL &x,LL y) { x += y; if (x >= mod) x -= mod; }
    
    void Calc() {
        for (int i = 0; i < (int)B.size(); ++i) Insert(B[i]);
        LL cnt[2] = {0, 0}, r = 0, now;
        for (int i = 60; ~i; --i) if (b[i]) r ++;
        for (int k = 60; ~k; --k) {
            bool flag = 0; cnt[0] = cnt[1] = 0;
            for (int i = 60; ~i; --i) if ((b[i] >> k) & 1) flag = 1;
            for (int i = 0; i < (int)A.size(); ++i) cnt[(dis[A[i]] >> k) & 1] ++;
            now = cnt[0] * (cnt[0] - 1) / 2 + cnt[1] * (cnt[1] - 1) / 2; now %= mod;
            if (flag) {
                if (r >= 1) mul(now, mi[r - 1]); 
                mul(now, mi[k]);
                add(Ans, now);
            }
            now = cnt[0] * cnt[1];
            if (flag) { if (r >= 1) mul(now, mi[r - 1]); }
            else mul(now, mi[r]);
            mul(now, mi[k]);
            add(Ans, now);
        }
        Clear();
    }
    
    int main() {
        int n = read(), m = read();
        mi[0] = 1; 
        for (int i = 1; i <= 62; ++i) mi[i] = mi[i - 1] * 2 % mod;
        for (int i = 1; i <= m; ++i) add_edge();
        for (int i = 1; i <= n; ++i) {
            if (!vis[i]) {
                dfs(i);
                Calc();
            }
        }
        cout << Ans;
        return 0;
    }
  • 相关阅读:
    (五)STL序列容器(deque)
    (四)STL序列容器(vector)
    (三)STL序列容器(array)
    (六)c语言之指针与函数、数组用法
    (五)c语言之内存分配
    (三)c++模板函数与函数模板详解
    Linux基础(03)gdb调试
    Linux基础(02)MakeFile的创建和使用
    Linux基础(01)开发环境的搭建
    Windows的socket编程
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10381648.html
Copyright © 2011-2022 走看看