给定 x, k ,求满足 x + y = x | y 的第 k 小的正整数 y 。 | 是二进制的或(or)运算,例如 3 | 5 = 7。
比如当 x=5,k=1时返回 2,因为5+1=6 不等于 5|1=5,而 5+2=7 等于 5 | 2 = 7。
给定 x, k ,求满足 x + y = x | y 的第 k 小的正整数 y 。 | 是二进制的或(or)运算,例如 3 | 5 = 7。
比如当 x=5,k=1时返回 2,因为5+1=6 不等于 5|1=5,而 5+2=7 等于 5 | 2 = 7。
每组测试用例仅包含一组数据,每组数据为两个正整数 x , k。 满足 0 < x , k ≤ 2,000,000,000。
输出一个数y。
5 1
2
#include <iostream>
#include <bitset>
using namespace std;
int main() {
unsigned long long x, y = 1, k;
cin >> x >> k;
std::bitset<64> xbs(x), kbs(k);
for (size_t i = 0, kpos = 0; i < xbs.size(); ++i) {
if (! xbs.test(i)) { // xbs[i] == 0
xbs.set(i, kbs[kpos++]);
}
}
y = xbs.to_ullong();
y ^= x;
cout << y << endl;
return 0;
}
import java.util.*;
import java.math.BigInteger;
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int x=sc.nextInt();
int k=sc.nextInt();
StringBuilder res=new StringBuilder();
String k_bin=Integer.toString(k, 2);
int index=k_bin.length()-1;
while(k!=0){
if((x&1)==0){
res.append(k_bin.charAt(index--));
k/=2;
}else{
res.append("0");
}
x>>>=1;
}
BigInteger num=new BigInteger(res.reverse().toString(), 2);
System.out.println(num);
sc.nextLine();
}
}
}
如果或要和加的运算结果相同,i在x的为0的位上可以是0,也可以是1;在x的为1的位上只能是0。所以x的二进制表示为0的位就是可用的“数位”,可以将k的二进制直接“映射”过去。而为1的位只能是0。这样就构建出了结果的二进制表示字符串。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while(scan.hasNext()){
long x = scan.nextInt();
long k = scan.nextInt();
long bitNum = 1; //指向x的当前位
long ans =0 ; //y的各位的值累加,累加完毕得到y
while( k >0){
if( (x & bitNum )== 0){ //如果当前x位为0
ans += (bitNum*(k & 1)); //则将k的最后一位取出来与填入x对应的为零的位并累加这一位的值
k = k >> 1; //k取出最后一位,即向右移一位
}
//上面无论x的当前位为0或1,bitNum都向左移一位
bitNum = bitNum << 1;
}
System.out.println(ans);//最后输出ans,即是y的值。
}
}
}
#include <iostream>
#include <vector>
using namespace std;
int main(){
int x,k;
while(cin>>x>>k){
long i=1,R=0,n=0;
vector<long>vec;
vector<long> v;
while(k!=0){
v.push_back(k%2);
k=k/2;
n++;
}
while(n>0){
if(!(x&i)){
vec.push_back(i);
n--;
}
i=i<<1;
}
for(i=0;i<vec.size();i++){
if(v[i]==1)
R+=vec[i];
}
cout<<R<<endl;
}
return 0;
}
#include <iostream>
#include <bitset>
using namespace std;
int main() {
unsigned long long x, y = 1, k;
cin >> x >> k;
unsigned long temp = ~x;
y = 0;
int ct=0;
while(temp){
if(temp & 0x01){
y|=(k & 0x01)<<ct;
k >>= 1;
}
temp>>=1;
ct++;
}
cout << y << endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
long long x, k, i = 0, res = 0;
cin >> x >> k;
while (k) {
while ((x&(1ll<<i)) != 0) ++i;
if (k&1) res += (1ll<<i);
k >>= 1;
++i;
}
cout << res << "\n";
} 题意
给定两个正整数 x, k (0 < x, k < 2 0000 0000),求第k个满足 x + y = x | y 的 y (正整数)
思路
要使 x + y = x | y 则 x 和 y 的二进制表示1和1之间的位置应该是不重合的,即 x & y = 0
则把k的二进制表示依次对应到x的二进制表示上为0的位置,其余空位添上0则为答案
举例 n = 5, k = 3
5 -> 0b 0101
3 -> 0b 0011
ans 0b 1010
(将k的1依次放到n上0的位置,其余空位添上0)
注意
由于x,k最大范围为2亿,因此极限情况为 x = k = 2 ^ 30 - 1 = 0b111...1111(连续30个1),则最终答案为0b111...11100000...0000(30个1接30个0),60位,因此最终结果需要用long表示。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int x = input.nextInt();
int k = input.nextInt();
StringBuilder sb = new StringBuilder();
while (k > 0) {
if ((x & 1) == 1) {
sb.append(0);
} else {
sb.append(k & 1);
k >>= 1;
}
x >>= 1;
}
long ans = Long.parseLong(sb.reverse().toString(), 2);
System.out.println(ans);
}
}
import java.util.Scanner;
public class JRTT3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
long x = scanner.nextLong();
long k = scanner.nextLong();
System.out.println(getNum(x,k));
}
}
public static long getNum(long x, long k) {
long bitNum = 1;
long num = 0;
//目标是把k的各位依次填在x中是0的位上
//bitNum用来移动到x中零的位置,然后把k的最低位放在x的零位上, k左移,将下一位变成最低位,bitNum一直左移,
//直到x中的下一个为0的位上。
while(k!=0){
if((x & bitNum) == 0){//x中当前bitNUM为0的话,把k的最低位放在这儿
//k&1是将k的最低位取出来, bitNum*(k&1)的结果就是得到bitNum位和当前k的最低位一样的一个数,而其它位都是0
//而num原来的bitNum为肯定为0,num+(bitNum*(k&1)) 就将k的最低位放在x的这个零上了。
num += (bitNum*(k & 1));
k >>= 1;
}
bitNum <<= 1; //bitNum的1一直左移到x中第k个零的位置
}
return num;
}
/*public static long getNum(long x, long k) {
long kMin = 1;
while (k != 0) {
if (isOK(x, kMin)) {
k--;
}
kMin++;
}
return --kMin;
}
public static boolean isOK(long x, long y) {
return (x + y) == (x | y);
}*/
}
#include <stdio.h>
#include <math.h>
int main()
{
long x,k;
while(scanf("%ld%ld",&x,&k)!=EOF)
{
int index_0[1000];
long y=0;
int digit=0,count=0;
int i=0,j;
while(x!=0)
{
if(x%2 == 0)
{
index_0[i] = digit;
i++;
}
digit++;
x = x/2;
}
for(j=i;j<=100;j++)
{
index_0[j] = digit;
digit++;
}
while(k!=0)
{
if(k%2 == 1)
{
y = y+(long)pow(2,index_0[count]);
}
count++;
k = k/2;
}
printf("%ld\n",y);
}
return 0;
}
#include <iostream>
using namespace std;
int main()
{
long long x, k;
cin>>x>>k;
long long bitNum = 1;
long long ans = 0;
while(k)
{
if((x & bitNum) == 0)
{
ans += (bitNum * (k & 1));
k >>= 1;
}
bitNum <<= 1;
}
cout<<ans<<endl;
return 0;
}
(x & bitNum) == 0 说明x该位为0,可以把k的当前最后一位填入,用 (k & 1) 取出最后一位,用 ans += (bitNum * (k & 1)) 把k的最后一位填入到当前bitNum指向的位置。 填完后,k右移一位,去掉已经被填过的最后一位,bitNum也向左走一位,避免重复填入x的某个位置。 若x的某个位置为1,则跳过该位置,向左走一位并观察是否可以填入。 两次bitNum向左走一位,合并成一句 bitNum <<= 1;
#include <iostream>
using namespace std;
int main()
{
long long x, k;
cin >> x >> k;
long long bitNum = 1;
long long ans = 0;
//目标是把k的各位依次填在x中是0的位上
//bitNum用来移动到x中零的位置,然后把k的最低位放在x的零位上, k左移,将下一位变成最低位,bitNum一直左移,知道x中的下一个为0的位上。
while (k)
{
if ((x & bitNum) == 0) //x中当前bitNUM为0的话,把k的最低位放在这儿
{
ans += (bitNum*(k & 1)); //k&1是将k的最低位取出来, bitNum*(k&1)的结果就是得到bitNum位和当前k的最低位一样的一个数,而其它位都是0
//而ans原来的bitNum为肯定为0,ans+(bitNum*(k&1)) 就将k的最低位放在x的这个零上了。
k >>= 1;
}
bitNum <<= 1; //bitNum的1一直左移到x中第k个零的位置
}
cout << ans << endl;
return 0;
}
Python 3
x, k = map(int, input().split())
bit = 1
ans = 0
while k:
if x & 1 == 0:
ans += bit*(k&1)
k >>= 1
x >>= 1
bit <<= 1
print(ans)
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main{
public static void main(String args []){
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine().toString();
String arrs[] = str.split(" ");
long x=0;
long k=0;
x = Long.parseLong(arrs[0]);
k = Long.parseLong(arrs[1]);
String[] strX = Long.toBinaryString(x).split("");
String[] strK = Long.toBinaryString(k).split("");
List<String> strXList = new ArrayList<String>(Arrays.asList(strX));
List<String> strKList = new ArrayList<String>(Arrays.asList(strK));
int i = 0;
boolean over = false;
int j = 0;
for(i = strKList.size() - 1;i>-1;i--){
while (!over && j< strXList.size()){
int index = strXList.size() - j - 1;
if (!strXList.get(index).equals("0")){
j++;
continue;
}else {
strXList.set(index,strKList.get(i));
j++;
break;
}
}
if (j==strXList.size()){
over = true;
}
if (over){
strXList.add(0,strKList.get(i));
continue;
}
}
String tempStr = "";
for (String s : strXList) {
tempStr+=s;
}
long y = Long.valueOf(tempStr,2) - x;
System.out.println(y);
}
} #include<bits/stdc++.h>
#include<iostream>
using namespace std;
int main(){
long long x,k,ans=0,bitnum=1;
cin>>x>>k;
while(k!=0){
while(bitnum&x)
bitnum*=2;
ans+=bitnum*(k%2);
bitnum*=2;
k/=2;
}
cout<<ans;
return 0;
} 必须向大佬献上我的瑞斯拜。另,左移右移可以通过乘二除二完成,取末位可以通过模二完成,不一定要通过位操作,忘了的话可以用普通的运算代替,但是对某些题目说不定会时间不够。
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
long x = scanner.nextLong();
long k = scanner.nextLong();
long t = ~x;
long mask = 1;
for(int i=0;i<64;++i, mask<<=1){
if((mask & t)==0)continue;
if( (k&1)==0){
// clear ith bit
t &= (~mask);
}
k>>>=1;
}
System.out.println(t);
}
} import java.math.BigInteger;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
try {
while (scan.hasNext()) {
long x = scan.nextLong();
long k = scan.nextLong();
findY(x, k);
}
} finally {
scan.close();
}
}
private static void findY(long x, long k) {
String xStr = Long.toBinaryString(x);
String kStr = Long.toBinaryString(k);
StringBuilder y = new StringBuilder();
int xPos = xStr.length()-1;
int kPos = kStr.length()-1;
while (xPos >=0 || kPos >=0) {
if (xPos >=0 && xStr.charAt(xPos) == '1') {
y.append("0");
} else {
y.append(kPos >=0 ? kStr.charAt(kPos) : '0');
kPos--;
}
xPos--;
}
System.out.print(new BigInteger(y.reverse().toString(), 2));
}
}