• 【每日一题】补档 AGC015D A or...or B Problem | 构造 | 困难


    题目内容

    原题链接

    给定一个区间 [ A , B ] [A,B] [A,B] ,从中选出两个数 x x x y y y x x x 可以等于 y y y ,问 x x x y y y 的结果可以得到多少个不同的数。

    数据范围

    • 0 ≤ A ≤ B < 2 60 0\leq A\leq B<2^{60} 0AB<260

    题解

    如果 A = B A=B A=B,那么答案就是 1 1 1 。特判即可。

    对于 [ A , B ] [A,B] [A,B] 中的数, A A A B B B 的二进制表示前缀中相同的部分或运算后的值必然是确定的,所以这部分可以不用考虑了。

    举个例子: A = 13 = 110 0 2 , B = 15 = 111 1 2 A=13=1100_2,B=15=1111_2 A=13=11002,B=15=11112,两者二进制都是以 11 11 11 开头的,这部分就是确定的,故这部分可以不用考虑了。

    可以将其重新设置为 A = 0 0 2 , B = 1 1 2 A=00_2,B=11_2 A=002,B=112

    B > A B>A B>A ,故两者从高位到低位的第一个不同的二进制数位 k k k k k k 必然是最高位。

    那么我们可以把可选择的数 x x x y y y 分为三部分,其中 x ≥ y x\geq y xy

    • 选择 x k = 0 , y k = 0 x_k=0,y_k=0 xk=0,yk=0,取值范围为: [ A , 2 k − 1 ] [A, 2^k-1] [A,2k1]
    • 选择 x k = 1 , y k = 0 x_k=1,y_k=0 xk=1,yk=0,取值范围为: [ 2 k + A , 2 k + 1 − 1 ] [2^k+A, 2^{k+1}-1] [2k+A,2k+11]
    • 选择 x k = 1 , y k = 1 x_k=1,y_k=1 xk=1,yk=1,取值范围为: [ 2 k , 2 k + 2 s + 1 − 1 ] [2^k, 2^k+2^{s+1}-1] [2k,2k+2s+11] ,其中 s s s 为从高位到低位第二个为 1 1 1 的二进制位,当不存在时, s = − 1 s=-1 s=1

    对于 x k = 0 , y k = 0 x_k=0,y_k=0 xk=0,yk=0,由于取值最小值为 A A A ,取值最大值为 2 k − 1 2^k-1 2k1 ,故或运算的值必然在这个范围内。
    具体构造出值 v ∈ [ A , 2 k − 1 ] v\in[A, 2^k-1] v[A,2k1],令 x = y = v x=y=v x=y=v 即可。

    对于 x k = 1 , y k = 0 x_k=1,y_k=0 xk=1,yk=0,第 k k k 位或运算结果为 1 1 1 ,那么只需要考虑低 k − 1 k-1 k1 位。因为 y ≥ A y\geq A yA ,所以或运算的结果必然 ≥ A \geq A A ,但是低 k − 1 k-1 k1 位至多是全部为 1 1 1 ,即 2 k − 1 2^k-1 2k1
    具体构造出值 v ∈ [ 2 k + A , 2 k + 1 − 1 ] v\in[2^k+A, 2^{k+1}-1] v[2k+A,2k+11],令 x = 2 k , y = v − 2 k x=2^k,y=v-2^k x=2k,y=v2k 即可。

    对于 x k = 1 , y k = 1 x_k=1,y_k=1 xk=1,yk=1,如果 B = 2 k B=2^k B=2k ,那么只能选择一个数。
    否则 B > 2 k B>2^k B>2k s s s 为从高位到低位第二个为 1 1 1 的二进制位。

    对于 b i t ∈ ( s , k ) bit\in(s,k) bit(s,k) 的二进制位 b i t bit bit ,这些必然不可能为 1 1 1
    那么 v k , v k − 1 , ⋯   , v s + 1 v_k,v_{k-1},\cdots,v_{s+1} vk,vk1,,vs+1 这些二进制位都已确定。那么可以构造出 [ 2 k , 2 k + 2 s + 1 − 1 ] [2^k, 2^k+2^{s+1}-1] [2k,2k+2s+11]
    具体构造出值 v ∈ [ 2 k , 2 k + 2 s + 1 − 1 ] v\in[2^k, 2^{k}+2^{s+1}-1] v[2k,2k+2s+11]

    • v < 2 k + 2 s + 1 − 1 v<2^{k}+2^{s+1}-1 v<2k+2s+11 x = v , y = 2 k x=v,y=2^k x=v,y=2k
    • v = 2 k + 2 s + 1 − 1 v=2^{k}+2^{s+1}-1 v=2k+2s+11 x = 2 k + 2 s , y = 2 k + 2 s − 1 x=2^k+2^{s},y=2^k+2^{s}-1 x=2k+2s,y=2k+2s1

    当然,这里的 x k = 1 , y k = 0 x_k=1,y_k=0 xk=1,yk=0 x k = 1 , y k = 1 x_k=1,y_k=1 xk=1,yk=1 的取值区间可能会有交集。

    因为 2 k < 2 k + A 2^k<2^k+A 2k<2k+A ,所以必然是 2 k + 2 s + 1 − 1 ≥ 2 k + A 2^{k}+2^{s+1}-1\geq 2^k+A 2k+2s+112k+A ,即 2 s + 1 − 1 ≥ A 2^{s+1}-1\geq A 2s+11A ,即 2 s + 1 > A 2^{s+1}>A 2s+1>A ,此时 A A A 的二进制为 1 1 1 的最高位小于等于 B B B 的二进制为 1 1 1 的次高位。

    时间复杂度: O ( log ⁡ max ⁡ ( A , B ) ) O(\log \max(A,B)) O(logmax(A,B)) ,至多 60 60 60

    代码

    #include 
    using namespace std;
    
    typedef long long ll;
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        ll A, B;
        cin >> A >> B;
        if (A == B) {
            cout << "1\n";
            return 0;
        }
    
        vector<int> vecA(60), vecB(60);
        for (int i = 0; i < 60; ++i) {
            vecA[i] = A % 2;
            vecB[i] = B % 2;
            A /= 2;
            B /= 2;
        }
    
        while (!vecA.empty() && vecA.back() == vecB.back()) {
            vecA.pop_back();
            vecB.pop_back();
        }
    
        int n = int(vecA.size());
    
        reverse(vecA.begin(), vecA.end());
        reverse(vecB.begin(), vecB.end());
    
        int s = -1;
        for (int i = 1; i < vecB.size(); ++i) {
            if (vecB[i] == 1) {
                s = n - 1 - i;
                break;
            }
        }
    
        ll ans = 0;
    
        A = 0;
        for (int i = 0; i < vecA.size(); ++i) A = A * 2 + vecA[i];
    
        ll R = (1ll << (n - 1)) + (1ll << (s + 1)) - 1;
        ll L = A;
    
        if (R >= (1ll << (n - 1)) + A) {
            R = (1ll << n) - 1;
            ans = R - L + 1;
        } else {
            ans = R - L + 1;
            ans += (1ll << (n - 1)) - 1 - A + 1;
        }
    
        cout << ans << "\n";
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
  • 相关阅读:
    我赢助手小技巧:学会这三招,爆款内容视频完播率提高50%(中)
    CLIP与DINOv2的图像相似度对比
    Spring Boot发布2.6.2、2.5.8:升级log4j2到2.17.0
    选择排序--java(详解)
    Python_数据容器_集合set
    水平分库分表
    cookie 、localStorage 和 sessionStorage 区别
    LLM实现RPA
    transformer一统天下?depth-wise conv有话要说
    浙大MBA经验分享:在工作生活的缝隙中奋勇上岸
  • 原文地址:https://blog.csdn.net/weixin_43900869/article/details/133626039