P7717 「EZEC-10」序列 (并查集 + dfs)
并查集 + dfs
题目的限制容易想到并查集维护异或和的经典做法,由于异或和的传递性,可以维护
不同连通块相互独立,满足乘法原理。在同一个连通块内,确定一个值,其他值也确定(根据
考虑建 01 trie,那么从大到小考虑方案数,显然限制只关心当前
当
- 如果
有两个儿子,那么继续往下两个儿子递归。 - 如果有一个儿子,那么这一位最大值有两种,一种为
,直接贡献 方案数(之后的位随便选);一种为 ,继续递归。
否则:
- 如果
有两个儿子,那么无解。 - 如有有一个儿子,那么继续递归。
复杂度
#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back
using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 5e5 + 10, mod = 1e9 + 7;
bool flg;
i64 n, m, k, ans = 1, ret, tot;
i64 fa[N], d[N];
std::vector<int> v[N];
int tr[N * 30][2];
int find(int x) {
if(x == fa[x]) return x;
int rt = find(fa[x]);
d[x] ^= d[fa[x]];
return fa[x] = rt;
}
void merge(int x, int y, i64 z) {
int fx = find(x), fy = find(y);
if(fx == fy) {
if(d[x] ^ d[y] ^ z) flg = 1;
} else {
fa[fx] = fy;
d[fx] ^= z ^ d[x] ^ d[y]; //为什么这样写?
}
}
i64 qpow(i64 a, i64 b) {
i64 ret = 1;
while(b) {
if(b & 1) ret = ret * a % mod;
a = a * a % mod;
b >>= 1;
}
return ret;
}
void init() {
for(int i = 0; i <= tot; i++) tr[i][0] = tr[i][1] = 0;
ret = tot = 0;
}
void insert(i64 x) {
int u = 0;
for(int i = 29; i >= 0; i--) {
int c = (x >> i) & 1;
if(!tr[u][c]) tr[u][c] = ++tot;
u = tr[u][c];
}
}
i64 dfs(int u, i64 dep) {
if(dep == -1) {
return 1;
}
int vis0 = tr[u][0], vis1 = tr[u][1];
if((k >> dep) & 1LL) {
if(vis0 && vis1) {
return (dfs(tr[u][0], dep - 1) + dfs(tr[u][1], dep - 1)) % mod;
} else if(vis0) {
ret = (ret + qpow(2, dep)) % mod;
return (qpow(2, dep) + dfs(tr[u][0], dep - 1)) % mod;
} else if(vis1) {
ret = (ret + qpow(2, dep)) % mod;
return (qpow(2, dep) + dfs(tr[u][1], dep - 1)) % mod;
}
} else {
if(vis0 && vis1) return 0;
else if(vis0) return dfs(tr[u][0], dep - 1);
else if(vis1) return dfs(tr[u][1], dep - 1);
}
return 0;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> m >> k;
for(int i = 1; i <= n; i++) fa[i] = i;
for(int i = 1; i <= m; i++) {
i64 x, y, z;
std::cin >> x >> y >> z;
merge(x, y, z);
}
if(flg) {
std::cout << "0\n";
return 0;
}
for(int i = 1; i <= n; i++) {
int f = find(i);
v[f].pb(i);
}
for(int i = 1; i <= n; i++) {
if(v[i].size()) {
init();
for(auto x : v[i]) {
insert(d[x]);
}
ans = ans * dfs(0, 29) % mod;
}
}
std::cout << ans << "\n";
return 0;
}
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具