276D

贪心

想了一会觉得没什么很好的方法,看了题解

我们枚举每个二进制位,对于l,r如果这位相同就异或到答案里,否则停止,这里肯定是r比l大,也就是r这位是1而l是0,那么我们就让r这位选1,l选0,然后把l从这位-1直到0每位全部赋成1,这样就是答案

为什么是对的呢?考虑如果这位不同,那么之前的位全部都是相同的,又因为l<=r,所以肯定这位l是0,r是1,所以我们把r后面所有位改成0也是符合的,假设现在的r=x,因为这样x的肯定是<=r,并且因为l这位是0,而之前所有位相等,所以x肯定>l,那么也就是说选的x是符合的,那么另外的一个y呢?y之前所有位和x是相同的,但是这位是0,有因为r这位是1,那么我们把后面所有位赋成1还是<r的,有因为之前所有位和l是一样的,把后面赋成1肯定是>=l的。

然后考虑如果这位相同,为什么我们不能改掉两个数中某一个的这位呢?如果这两位l和r都是0,那么我们把一个数这位赋成1,因为之前相同,那么现在这个数就>r了,不满足,如果两位都是1,因为之前所有位和l相同,那么改成0后就<l,也不满足。

感觉这道题挺巧妙的,只用不到十行就解决了问题,然而想法还是比较巧妙。看来异或问题不仅可以用trie,线性基取最大值,有时得仔细结合题目分析就能得出简单的结论。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll l, r, ans;
int main()
{
    cin >> l >> r;
    for(int i = 61; i >= 0; --i)     
    {
        ans ^= (l & (1ll << i)) ^ (r & (1ll << i));
        if((l & (1ll << i)) != (r & (1ll << i))) 
        {
            for(int j = i - 1; j >= 0; --j) ans ^= (1ll << j);
            break;
        }
    }
    cout << ans;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7595634.html