[ AtCoder Grand Contest 031] C - Differ by 1 Bit (分治)
作者:互联网
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
-
根据题目猜想出一些结论。
-
二进制问题考虑分治思想。
标签:AtCoder,Differ,ch,分治,Contest,二进制,奇数,mid,位数 来源: https://www.cnblogs.com/BaseAI/p/13960215.html