题解 CF1218D【Xor Spanning Tree】

萌萌 FWT 题。

仙人掌满足任意一条边只在至多一个环上,因此要求生成树,只需要每个环断一条边即可。显然生成树上边权异或和等于所有边异或和再异或上所有断的边。

设所有边异或和为 s,第 i 个环上有 ci,j 条边权为 j 的边。

F0(z)=[z=s]Fi(z)=ci,z。定义 (FxorG)(z)=ixorj=zF(i)G(j)

使用 FWT 计算出 xorFi,其第 z 项的值即为边权异或和为 z 的生成树个数,从小到大枚举 z 找出第一个可行解并输出即可。

需要注意的是,在第 31 个测试点,最小异或生成树个数对 109+7 取模恰好余 0,会使得我们漏掉最优解,因此需要双模数。

时间复杂度为 O(knlogn),其中 k 为环数,值域视为与 n 同阶。

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(ll x=(y);x<=(z);x++)
#define per(x,y,z) for(ll x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;

mt19937 rnd(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
ll randint(ll L, ll R) {
	uniform_int_distribution<ll> dist(L, R);
	return dist(rnd);
}

template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}

const ll N = 131072, mod1 = 1e9+7, mod2 = 1e9+9;

ll n, m, xsum, F[N], G[N], f[N], g[N], fa[N], val[N], dfn[N], tms;
vector<tuple<ll, ll>> e[N];
vector<vector<ll>> cyc;

template<ll mod, ll flg>
void FWT_xor(ll* a, ll n) {
	ll mul = flg == +1 ? 1 : (mod + 1) / 2;
	for(ll o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
		for(ll i = 0; i < n; i += o)
			rep(j, 0, k-1) {
				a[i+j] += a[i+j+k];
				a[i+j+k] = a[i+j] + 2 * (mod - a[i+j+k]);
				a[i+j] *= mul;
				a[i+j+k] *= mul;
				a[i+j] %= mod;
				a[i+j+k] %= mod;
			}
}

void dfs(ll u, ll f, ll w) {
	fa[u] = f;
	val[u] = w;
	dfn[u] = ++tms;
	for(auto& i : e[u]) {
		ll v = get<0>(i), w = get<1>(i);
		if(v != f) {
			if(!dfn[v]) dfs(v, u, w);
			else if(dfn[v] < dfn[u]) {
				cyc.push_back({});
				cyc.back().push_back(w);
				for(ll k = u; k != v; k = fa[k]) cyc.back().push_back(val[k]);
			}
		}
	}
}

int main() {
	scanf("%lld%lld", &n, &m);
	rep(i, 1, m) {
		ll u, v, w;
		scanf("%lld%lld%lld", &u, &v, &w);
		e[u].emplace_back(v, w);
		e[v].emplace_back(u, w);
		xsum ^= w;
	}
	F[xsum] = G[xsum] = 1;
	FWT_xor<mod1, +1>(F, N);
	FWT_xor<mod2, +1>(G, N);
	dfs(1, 0, 0);
	for(auto& c : cyc) {
		memset(f, 0, sizeof(f));
		memset(g, 0, sizeof(g));
		for(ll i : c) ++f[i], ++g[i];
		FWT_xor<mod1, +1>(f, N);
		FWT_xor<mod2, +1>(g, N);
		rep(i, 0, N-1) {
			F[i] = F[i] * f[i] % mod1;
			G[i] = G[i] * g[i] % mod2;
		}
	}
	FWT_xor<mod1, -1>(F, N);
	FWT_xor<mod2, -1>(G, N);
	rep(i, 0, N-1) {
		if(F[i] || G[i]) {
			printf("%lld %lld\n", i, F[i]);
			break;
		}
	}
	return 0;
}
posted @   rui_er  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2021-08-20 【CF 985F Isomorphic Strings】解题报告(字符串哈希)
2021-08-20 清华附中信息学竞赛 20210820 小测题解
点击右上角即可分享
微信分享提示