Problem
Solution
前置
- 格雷码,有一些异同之处。
题解
-
结论1:有解的必要条件是 (A) 和 (B) 在二进制下不同的位数是奇数。
-
结论2:(A) 和 (B) 在二进制下不同的位数是奇数,那么就可以构造出一组解。换言之,(A) 和 (B) 在二进制下不同的位数是奇数,是有解的充分条件。
考虑用分治法构造一组解。设原问题为 (f(A,B,s)),(s) 是一个(01)序列,表示二进制下可以调整的位,其中(0)表示不可调整,(1)表示可以调整,原问题的 (s) 是一个长度为 (n) 的全为 (1) 的序列。
假设 (A,B) 第 (x) 位是不同的,那么固定第 (x) 位,使得构造的解左半部分第 (x) 位全和 (A) 相同,右半部分第 (x) 位全和 (B) 相同,此时 (s') 将在原 (s) 的基础上将第 (x) 位修改为(0)。将 (A) 剩下可以调整的任意一位修改,令其为 (mid)。则原问题就变成了 (f(A,mid,s')) 和 (f(mid,B,s'))。注意 (mid->B) (也就是右半部分)(mid) 的第 (x) 位也要和 (B) 一样。
Code
Talk is cheap.Show me the code.
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
return x * f;
}
int n,A,B;
int Calc(int x) {
if(x==0) return 0;
int res = 0;
while(x) {
++res; x -= x&-x;
}
return res;
}
void Dfs(int a,int b,int s) {
if(s) {
int x = (a^b) & s; x = x & -x;
s ^= x;
int mid = a ^ (s & -s);
Dfs(a,mid,s); Dfs(mid^x,b,s);
} else printf("%d ",a);
}
int main()
{
n = read(); A = read(); B = read();
if(Calc(A^B) & 1) {
puts("YES"); Dfs(A,B,(1<<n)-1);
} else puts("NO");
return 0;
}
/*
2 1 3
YES
1 0 2 3
*/
Summary
-
根据题目猜想出一些结论。
-
二进制问题考虑分治思想。