2026牛客暑期多校2 H 题思路分享(构造)
题意
对于 \(n\) 维超立方体,删掉 \(a,b\) 两点,构造一种方案使得剩余点两两配对,满足配对的点二进制中恰好有两位不同.
\(2\le n \le 22\).
思路
配对点有两位不同,即 \(popcount\) 奇偶性相同,因此必须满足 \(popcount(a) \equiv popcount(b) \pmod 2\),否则奇点和偶点均有奇数个元素.
记 \(a\) 和 \(b\) 某个不同位为 \(c\),将所有数 \(c\) 位删掉后,\(popcount(a')\not\equiv popcount(b') \pmod 2\),于是可以找一条在 \(n-1\) 维超立方体中,\(a'\) 到 \(b'\) 的哈密顿路径,记为 \(P\).
我们想要在原超立方体中,\(popcount\) 全奇和全偶的两条路径,可以自由地将 \(1\) 或 \(0\) 重新插入 \(P\) 每个元素第 \(c\) 位,保证路径所有元素奇偶性一致即可,显然地,构造两条路径所有插入的值都是确定的,并且并集为 \([0\cdots 2^n-1]\).
时间复杂度 \(\mathcal{O}(2^n)\).
代码
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int erase(int x,int k){
int low = x&((1<<k)-1);
int high = x>>k+1<<k;
return high|low;
}
int insert(int x,int k,int bit){
int low = x&((1<<k)-1);
int high = x>>k<<k;
return (high<<1)|(bit<<k)|low;
}
void solve(){
int n,a,b;
cin >> n >> a >> b;
if ((__builtin_popcount(a)&1)!=(__builtin_popcount(b)&1)){
cout << "NO" << '\n';
return;
}
cout << "YES" << '\n';
int k = __builtin_ctz(a^b);
int s = erase(a,k);
int t = erase(b,k);
vector<int> res(1<<n-1);
function<void(int,int,int,int,int)> dfs = [&](int mask,int s,int t,int l,int r){
if (r==l+1){
res[l] = s;
res[r] = t;
return;
}
int mid = l+r >> 1;
int c = __builtin_ctz((s^t)&mask);
int nmask = mask^(1<<c);
int j = __builtin_ctz(nmask);
int x = s^(1<<j);
int y = x^(1<<c);
dfs(nmask,s,x,l,mid);
dfs(nmask,y,t,mid+1,r);
};
dfs((1<<n-1)-1,s,t,0,(1<<n-1)-1);
vector<int> res1(1<<n-1),res2(1<<n-1);
for (int i=0;i<1<<n-1;i++){
res1[i] = insert(res[i],k,(__builtin_popcount(res[i])&1)^1);
}
for (int i=0;i<1<<n-1;i++){
res2[i] = insert(res[i],k,(__builtin_popcount(res[i])&1));
}
if (__builtin_popcount(a)&1){
for (int i=1;i<(1<<n-1)-1;i+=2){
cout << res1[i] << ' ' << res1[i+1] << '\n';
}
for (int i=0;i<1<<n-1;i+=2){
cout << res2[i] << ' ' << res2[i+1] << '\n';
}
}
else{
for (int i=1;i<(1<<n-1)-1;i+=2){
cout << res2[i] << ' ' << res2[i+1] << '\n';
}
for (int i=0;i<1<<n-1;i+=2){
cout << res1[i] << ' ' << res1[i+1] << '\n';
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号