agc031 C Differ by 1 Bit

传送门:
https://atcoder.jp/contests/agc031/tasks/agc031_c

题解:

考虑把x xor y,问题变成从0->x xor y

因为 2 n − 1 2^n-1 2n1是奇数,所有 x   x o r   y x~xor~y x xor y有偶数个1无解。

由于我们任意交换一下位是没有关系的,所以考虑就是要构造出:
000 … − > 111 ( k ( k 奇 数 ) 个 1 ) 00 … … 000…->111(k(k奇数)个1)00…… 000>111(k(k)1)00

s ( n , k ) s(n,k) s(n,k)表示有k个1时的答案。

当k=1时,显然有:
强制第一位为0,后面任意走完,可以通过n-1,k任意的情况推来
然后把第一位改为1,后面的倒着走即可走回后面全0

k>=3时

考虑固定第一位为0,后面走 s ( n − 1 , k − 2 ) s(n-1,k-2) s(n1,k2)

把第一位改为1,然后现在把后面的位视为全0(走的时候异或一下即可),走s(n-1,1),注意1的位置要移到n-k+1那里去。

#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define ll long long
#define db double
#define ld long double
#define pp printf
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i <  B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define pb push_back
#define sz size()
using namespace std;

vector<int> a[18][18];


int z[1 << 18];
int us[20], to[20];

void zh(int x, int y, int n) {
	ff(i, 0, n) us[i] = 0;
	ff(i, 0, n) {
		ff(j, 0, n) if((x >> i & 1) == (y >> j & 1) && !us[j])
			{ us[j] = 1; to[i] = j; break;}
	}
	ff(i, 0, 1 << n) {
		int s = 0;
		ff(j, 0, n) s += (i >> j & 1) * (1 << to[j]);
		z[i] = s;
	}
}

int n, x, y, c;

void pr(int x, int n) {
	fd(i, n - 1, 0) pp("%d", x >> i & 1); pp(" ");
}

int main() {
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
	n = 17;
	a[1][1].pb(0); a[1][1].pb(1);
	fo(i, 2, n) {
		int mx = 1 << (i - 1);
		ff(k, 0, a[i - 1][1].sz)
			a[i][1].pb(a[i - 1][1][k]);
		fd(k, a[i - 1][1].sz - 1, 0)
			a[i][1].pb(a[i - 1][1][k] + mx);
			
		for(int j = 3; j <= i; j += 2) {
			ff(k, 0, a[i - 1][j - 2].sz)
				a[i][j].pb(a[i - 1][j - 2][k]);
			int h = a[i - 1][j - 2][a[i - 1][j - 2].sz - 1];
			zh(1 << (i - 2), 1 << (i - j), i - 1);
			ff(k, 0, a[i - 1][1].sz)
				a[i][j].pb((z[a[i - 1][1][k]] ^ h) + (1 << (i - 1)));
		}
	}
	scanf("%d %d %d", &n, &x, &y);
	ff(i, 0, n) c += (x ^ y) >> i & 1;
	if(c % 2 == 0) {
		pp("NO\n"); return 0;
	}
	pp("YES\n");
	zh(a[n][c][a[n][c].sz - 1], x ^ y, n);
	ff(k, 0, a[n][c].sz) pp("%d ", z[a[n][c][k]] ^ x);
	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值