[ 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

  • 根据题目猜想出一些结论。

  • 二进制问题考虑分治思想

posted @ 2020-11-11 18:56  基地AI  阅读(143)  评论(0编辑  收藏  举报