I will no longer be|

yabnto

园龄:2年8个月粉丝:14关注:17

Compatible Numbers

Compatible Numbers

思路

对于一个数 x,如果想要构造一个数 y 使得 x&y=0 那么显然对于 x 的每一位:

  1. 如果当前位是 0,那么 y 这一位可以填 1,0
  2. 如果当前位是 1,那么 y 这一位可以填 0

那么对于用这种方式构造出来的数的一些位是可以互换的,而互换后的数显然也是满足要求的,所以问题就变成了,a1,a2,a3,,an,通过一些位的互换是否可以换成用上面的方法构造出来的数。

对于用上面的方法构造出来的数,如果当前数的二进制的某一位是 1,那么根据上面的规则,你不能将它变成 0,因为会多出一些可能,有后效性,但是对于某一位是 0, 它是不会多出新的方案的,那么我们就可以判断说通过上面的方法构造出来的数的最大值,是否可以被 a1,a2,a3,,an 中的任意一个数通过一些位的互换换出,那么要构造出最大值其实就是能变 1, 就变 1,也就是按位取反。

然后对于每一个数(a1,a2,a3,,an),我们把它看成二进制,搜索每一位是否换,然后换后得出的新数标记是否存在,最后对每个数按位取反后判是否曾经换出来了即可。

然后搜索部分是可以用 dp 来实现的,所以将搜索换成 dp 即可。

dpx 为数值 x 是否可以被数组 a 中的任意一个数换出来,能换出来则记录是从哪一个数换出来的,转移则是 dpx = dpy,其中 y 的二进制位与 x 的二进制位有且只有一个位置不同,而且不同的位置 y 是 0,x 是 1,初始状态为:dpai=ai

注:互换就是说那一位取反。

code

点击查看代码
#include <iostream>
using namespace std;
const int MaxN = 1e6 + 10, MaxM = 9e6 + 10;
int dp[MaxM], a[MaxN], n;
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i], dp[a[i]] = a[i];
}
for (int i = 0; i < MaxM; i++) {
if (dp[i]) {
for (int j = 0; (1 << j) < MaxM; j++) {
if (!(i & (1 << j)) && (i | (1 << j)) < MaxM) {
dp[(i | (1 << j))] = dp[i];
}
}
}
}
for (int i = 1; i <= n; i++) {
cout << (dp[((1 << 22) - 1) ^ a[i]] ? dp[((1 << 22) - 1) ^ a[i]] : -1) << " ";
}
return 0;
}

本文作者:yabnto

本文链接:https://www.cnblogs.com/ybtarr/p/17612410.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yabnto  阅读(50)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 光辉岁月 Audio artist
  3. 3 名前を呼ぶよ Audio artist
  4. 4 战歌 Audio artist
  5. 5 時を越えた想い Audio artist
  6. 6 所念皆星河 Audio artist
  7. 7 See you again Audio artist
光辉岁月 - Audio artist
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

Not available

点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起