根据题目描述可知是个特殊的仙人掌, 然后把环扣出来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; } /** **/
原文地址:https://www.cnblogs.com/CJLHY/p/11719574.html
时间: 2024-10-29 07:56:44