最大的位或(思维)
最大的位或
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1197 Accepted Submission(s): 484
Problem Description
B君和G君聊天的时候想到了如下的问题。
给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大。
其中|表示按位或,即C、 C++、 Java中的|运算。
给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大。
其中|表示按位或,即C、 C++、 Java中的|运算。
Input
包含至多10001组测试数据。
第一行有一个正整数,表示数据的组数。
接下来每一行表示一组数据,包含两个整数l,r。
保证 0 <= l <= r <= 1018。
第一行有一个正整数,表示数据的组数。
接下来每一行表示一组数据,包含两个整数l,r。
保证 0 <= l <= r <= 1018。
Output
对于每组数据输出一行,表示最大的位或。
Sample Input
5
1 10
0 1
1023 1024
233 322
1000000000000000000 1000000000000000000
Sample Output
15
1
2047
511
1000000000000000000
题解:让在l和r之间找两个数的最大或值,思路,先把十进制转化成二进制,分为两种情况,如果r的二进制长度比l长,那么肯定有11111在l和r之间,或值就是全是1,如果长度相同,只需要找后面开始不相同的位直接全1与r或就可以了
代码:
import java.util.Scanner; public class Main { private static Scanner cin; static{ cin = new Scanner(System.in); } public static char[] stringToChar(String s){ char arr[] = new char[s.length()]; for(int i = 0; i < s.length(); i++){ arr[i] = s.charAt(i); } return arr; } public static Long SystemChange(char[] s, int radix){ Long ans = 0L; //System.out.print("转换前: "); for(int i = 0; i < s.length; i++){ ans = ans * radix + s[i] - '0'; } //System.out.println("转换后: " + ans); return ans; } public static void main(String[] args) { int T; T = cin.nextInt(); Long l, r; while(T-- > 0){ l = cin.nextLong(); r = cin.nextLong(); if(l > r){ Long temp = l; l = r; r = temp; } String bl = l.toBinaryString(l); String br = r.toBinaryString(r); if(br.length() > bl.length()){ System.out.println(pow(br.length()) - 1); }else{ int i; for(i = 0; i < br.length(); i++){ if(bl.charAt(i) != br.charAt(i)) break; } long temp = pow(br.length() - i) - 1; System.out.println(r|temp); } } } private static long pow(int length) { long x = 1; while(length-- > 0){ x = x << 1; } return x; } }