Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) G - Xor-matic Number of the Graph 线性基好题

G - Xor-matic Number of the Graph

上一道题的加强版本,对于每个联通块需要按位算贡献。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
#define ull unsigned long long
using namespace std;

const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int n, m;
LL d[N], bin[N], num[2];
bool vis[N];
vector<PLI> edge[N];
vector<int> id;
struct Base {
    LL a[63];
    int cnt;
    void init() {
        memset(a, 0, sizeof(a));
        cnt = 0;
    }
    void add(LL x) {
        for(int j = 62; ~j; j--) {
            if((x >> j) & 1) {
                if(!a[j]) {a[j]=x; cnt++; break;}
                else x ^= a[j];
            }
        }
    }
} base;

void dfs(int u, int fa) {
    vis[u] = true;
    id.push_back(u);
    for(int i = 0; i < edge[u].size(); i++) {
        int v = edge[u][i].se; LL w = edge[u][i].fi;
        if(v == fa) continue;
        if(vis[v]) {
            base.add(d[u]^d[v]^w);
        } else {
            d[v] = d[u] ^ w;
            dfs(v, u);
        }
    }
}

int main() {
    base.pirnt();
    scanf("%d%d", &n, &m);
    for(int i=bin[0]=1; i <= n; i++)
        bin[i] = bin[i-1] * 2 % mod;
    for(int i = 1; i <= m; i++) {
        int u, v; LL w;
        scanf("%d%d%lld", &u, &v, &w);
        edge[u].push_back(mk(w, v));
        edge[v].push_back(mk(w, u));
    }

    LL ans = 0;
    for(int i = 1; i <= n; i++) {
        if(!vis[i]) {
            base.init();
            id.clear();
            dfs(i, 0);
            for(int j = 0; j <= 62; j++) {
                num[0] = 0, num[1] = 0;
                for(auto &x : id) {
                    num[(d[x]>>j)&1]++;
                }
                bool flag = false;
                for(int k = 0; k < 63; k++) {
                    if((base.a[k]>>j)&1) {
                        flag = true;
                        break;
                    }
                }

                LL tmp = num[0]*(num[0]-1)/2 + num[1]*(num[1]-1)/2;
                tmp %= mod;
                if(flag) ans = (ans + bin[j]*bin[base.cnt-1]%mod*tmp%mod) % mod;
                tmp = num[0] * num[1] % mod;
                if(flag) ans = (ans + bin[j]*bin[base.cnt-1]%mod*tmp%mod) % mod;
                else ans = (ans + bin[j]*bin[base.cnt]%mod*tmp%mod) % mod;
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}

/*
*/

 

posted @ 2018-10-04 12:18  NotNight  阅读(119)  评论(0编辑  收藏  举报