Hdu5969(最大或)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40984919/article/details/81367286

  这几天做fwj大佬在Vj上放出来的训练题,遇见很多思维题。比如下边这道题。

B君和G君聊天的时候想到了如下的问题。 
给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大。 
其中|表示按位或,即C、 C++、 Java中的|运算。

Input包含至多10001组测试数据。 
第一行有一个正整数,表示数据的组数。 
接下来每一行表示一组数据,包含两个整数l,r。 
保证 0 <= l <= r <= 10181018。Output对于每组数据输出一行,表示最大的位或。Sample Input

5
1 10
0 1
1023 1024
233 322
1000000000000000000 1000000000000000000

Sample Output

15
1
2047
511
1000000000000000000

题意:给你两个数l r让你输出l--r之间最大的按位或的结果(2个整数)

    在刚开始做这道题的时候,想到过肯定是是把最大的保存下来。然后在从下边的找一个出来。但是一直想不到怎么去找那个剩余的值。在fwj大佬在讲解题目之后。恍然大悟(顿时豁然开朗啊)。

接下来举个例子

5      101
6      110
7      111
8     1000
9     1001
10    1010
11    1011
12    1100
13    1101
14    1110
15    1111

1、我们先看5->10  在这个区间中。我们可以看到5的二进制位数和10的二进制位数是不相等的。那么我们就可在这两个数之间找到1个7(2进制为111)那么此时10|7为最大15;

2、当位数相同的情况下,比如8->10那么我们在去掉8和10(从二进制开始到找到不同)相同的位数;

     我们可以看到此时  8  剩下----- 00

                       10 剩下------10

      那么我们可以看到在00---->10之间我们可以找到一个01使得我们的按位或是最大的。

那么,根据这个想法。我们就可以很快的写出我们的代码了;

代码:

#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<math.h>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define close ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N=1000000+50;
const int INF=0x3f3f3f3f;
const double EPS = 1e-10;
ll mod = 1e9+7;

ll Get_Sum(ll l,ll r){
	ll numl[10000];
	ll numr[10000];
	memset(numl,-1,sizeof(numl));
    memset(numr,-1,sizeof(numr));
    
	int cntl = 0, cntr = 0;
	
	while(l){
		numl[cntl++] = l % 2;
		l /= 2;
	}
	while(r){
		numr[cntr++] = r % 2;
		r /= 2;
	}
	if(cntr > cntl) cout<<((ll)pow(2,cntr)-1)<<endl;
	else{
		int flag = 0;
		for(int i = cntr - 1; i >= 0; i--){
			if(numl[i] != numr[i]){
				flag = i;
				break;
			}
		}	
		ll ans = 0;
		for(int i = cntr - 1; i >= 0; i--){
			if(i < flag){
				ans += (ll)pow(2,i);
			}
			else if(numr[i] == 1){
				ans += (ll)pow(2,i);
			}
		}
		cout<<ans<<endl;	
	}
}

int main(){
	close;
	int t;
	cin>>t;
	while(t--){
		ll l, r;
		cin>>l>>r;
		if(l == r) cout<<r<<endl;
		else Get_Sum(l,r); 
	}
 	return 0;
}

/*
                ********
               ************
               ####....#.
             #..###.....##....
             ###.......######              ###            ###
                ...........               #...#          #...#
               ##*#######                 #.#.#          #.#.#
            ####*******######             #.#.#          #.#.#
           ...#***.****.*###....          #...#          #...#
           ....**********##.....           ###            ###
           ....****    *****....
             ####        ####
           ######        ######
##############################################################
#...#......#.##...#......#.##...#......#.##------------------#
###########################################------------------#
#..#....#....##..#....#....##..#....#....#####################
##########################################    #----------#
#.....#......##.....#......##.....#......#    #----------#
##########################################    #----------#
#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#
##########################################    ############
*/

大佬cqw的另一种思想(厉害!厉害!)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

//求最大位数 
int Max_Pow(ll x){
	int d = 0;
	while(x > 0){
		x >>= 1;
		d++;
	}
	return d;
}

int main(){
	int t;
	ll l, r, x, d, ans;
	scanf("%d",&t);
	while(t--){
		scanf("%I64dd%I64d",&l, &r);
		x = r ^ l;
		d = Max_Pow(x);
		ans = (1LL << d) - 1;
		printf("%I64d\n",R | x);
	}	
}

猜你喜欢

转载自blog.csdn.net/qq_40984919/article/details/81367286