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

Codeforces 1218D Xor Spanning Tree FWT

时间:2019-10-22 15:34:43      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:auto   void   mes   ace   push   make   xor   sizeof   nbsp   

根据题目描述可知是个特殊的仙人掌, 然后把环扣出来fwt算方案数就好了。

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

const int N = 1 << 17;
const int mod = (int)1e9 + 7;
const int mod2 = 998244353;

int n, m, xr, fa[N], fa_w[N];
int dfn[N], dfs_clock;
vector<PII> G[N];
vector<vector<int>> VV;

int a[N], b[N], c[N], d[N];

void dfs(int u, int pa) {
    dfn[u] = ++dfs_clock;
    for(auto &e : G[u]) {
        int v = e.se, w = e.fi;
        if(v == pa) continue;
        if(!dfn[v]) {
            fa[v] = u, fa_w[v] = w;
            dfs(v, u);
        }
        else if(dfn[v] > dfn[u]) {
            vector<int> V;
            int cur_xr = w;
            for(int cur = v; cur != u; cur = fa[cur]) {
                cur_xr ^= fa_w[cur];
            }
            V.push_back(cur_xr ^ w);
            for(int cur = v; cur != u; cur = fa[cur]) {
                V.push_back(cur_xr ^ fa_w[cur]);
            }
            xr ^= cur_xr;
            VV.push_back(V);
        }
    }
}

void fwt_xor(int *a, int n, int dft, int mod, int inv2) {
    for(int i = 1; i < n; i <<= 1) {
        for(int j = 0; j < n; j += i << 1) {
            for(int k = j; k < j + i; k++) {
                int x = a[k], y = a[i + k];
                a[k] = (x + y) % mod; a[i + k] = (x - y + mod) % mod;
                if(dft == -1) a[k] = 1LL * a[k] * inv2 % mod, a[i + k] = 1LL * a[i + k] * inv2 % mod;
            }
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back(mk(w, v));
        G[v].push_back(mk(w, u));
        xr ^= w;
    }
    dfs(1, 0);
    a[xr] = 1;
    c[xr] = 1;
    fwt_xor(a, 1 << 17, 1, mod, (mod + 1) >> 1);
    fwt_xor(c, 1 << 17, 1, mod2, (mod2 + 1) >> 1);
    for(auto &V : VV) {
        memset(b, 0, sizeof(b));
        memset(d, 0, sizeof(c));
        for(auto &t : V) b[t]++, d[t]++;
        fwt_xor(b, 1 << 17, 1, mod, (mod + 1) >> 1);
        fwt_xor(d, 1 << 17, 1, mod2, (mod2 + 1) >> 1);
        for(int i = 0; i < (1 << 17); i++) {
            a[i] = 1LL * a[i] * b[i] % mod;
            c[i] = 1LL * c[i] * d[i] % mod2;
        }
    }
    fwt_xor(a, 1 << 17, -1, mod, (mod + 1) >> 1);
    fwt_xor(c, 1 << 17, -1, mod2, (mod2 + 1) >> 1);
    for(int i = 0; i < (1 << 17); i++) {
        if(a[i] || c[i]) {
            printf("%d %d\n", i, a[i]);
            return 0;
        }
    }
    return 0;
}

/**
**/

 

Codeforces 1218D Xor Spanning Tree FWT

标签:auto   void   mes   ace   push   make   xor   sizeof   nbsp   

原文地址:https://www.cnblogs.com/CJLHY/p/11719574.html

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