给定 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)); } }