HDU

来源:互联网 发布:疯狂原始人 知乎 编辑:程序博客网 时间:2024/06/06 00:26

题目链接:HDU - 5969


题意:找出区间[L, R]中的两个数x、y,使x|y(位或)最大。


题解:位或是二进制运算,二进制中只有0和1,要使位或最大,就要使R位或后的1尽可能的多。因为位或的性质,不可能位或后使数的最高位大于R。所以其中一个数必须是R。首先要知道,在剩下的数中能使R增加的1的位数是有限的。那么能增加多少呢?能使L与R出现的L的最高不同位之后的低位全部变成1。

      例:R:10100010       能产生最大位或的数:R:10100010     位或结果:10111111

          L:10011000                          x:10011111

         可以将上面R的绿色位全部变成1。

这是因为一个数x从L开始增大到R,x与R出现的x的最高不同位不能超过L与R的L的最高不同位。如样例中x与R最高不同位不能超过红色位。因为能产生最的位或的x必须满足与R的最高不同位之后的位全部是1,如紫色的部分,这样位或后能使R的相同部分全变成1,而如果此时让紫色位1继续增多,那么会使x大于R,不满足条件。

操作:

1.取K = R ^ L;这样能将R与L所有不同的位都标记出来。例中的K = 00111010

2.求出求出K的最高位的位数d(例K的蓝色位),令x = (1 << d) - 1。这样能使最高不同位后的位全部变成1。例中的x = 00011111

3.ans = R | x


#include <bits/stdc++.h>using namespace std;//求出最高位int digit(long long K){    int d = 0;    while(K > 0){        K >>= 1;        d++;    }    return d;}int main(){    int T;    long long L, R, ans, K, x, d;    scanf("%d", &T);    while(T--){        scanf("%I64d%I64d", &L, &R);        K = R ^ L;        d = digit(K);        x = (1LL << d) - 1;        printf("%I64d\n", R | x);    }    return 0;}




         


原创粉丝点击