• 异或 [异或相关]


    感谢 Morning_Glory 赞助

    异或


    Descriptionmathcal{Description}

    给定 L,RL, R, 求
    i=LRj=LR ijsum_{i=L}^Rsum_{j=L}^R i⊕j
    L,R<=109L,R <=10^9 .


    Solutionmathcal{Solution}

    假设L=1,R=4L=1, R=4, 则将所有涉及到的数字转换为 二进制 如下 ,
     [1  0 0 12  0 1 03  0 1 14  1 0 0] \ egin{bmatrix} 1 | 0 0 1 \ 2 | 0 1 0 \ 3 | 0 1 1 \ 4 | 1 0 0 \ end{bmatrix}
    :按位处理 :

    202^0 为例,

     [1010] \ egin{bmatrix} 1 \ 0 \ 1 \ 0 \ end{bmatrix}
    每个数字都要与每个数字 异或 并且对答案造成贡献,

     0  num0,1  num1设 0 的数量为 num_0, 1 的数量的为 num_1

    1. 当前位置为 11, 对答案贡献为 num0num_0 .
    2. 当前位置为 00, 对答案贡献为 num1num_1 .

    综上该位答案为 2num1num0202*num_1*num_0*2^0 .


    num1,num0:求num_1, num_0:

    [0 0 00 0 10 1 00 1 11 0 01 0 11 1 01 1 1] egin{bmatrix} 0 0 0 \ 0 0 1 \ 0 1 0 \ 0 1 1 \ 1 0 0 \ 1 0 1 \ 1 1 0 \ 1 1 1 \ end{bmatrix}
    观察以上序列, 发现若当前位置为 2i2^i, 则 000..111...000..111...循环节长度为 2i+12^{i+1}.
    先来求 [0,N][0, N]2i2^i 位置的答案,

    num0=N+12i+12i+min{(N+1)%2i+1,2i} num1=Nnum0+1num_0 = lfloor frac{N+1}{2^{i+1}} floor* 2^i + min{(N+1)\%2^{i+1}, 2^i}\ \ num_1 = N-num_0+1

    然后 容斥 即可求出 [L,R][L, R]num0,num1num_0, num_1 .


    O(logN)复杂度 O(logN).


    Codemathcal{Code}

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ c = getchar(), flag = -1; break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int mod = 1e9 + 7;
    
    int L;
    int R;
    int Ans;
    int pw[50];
    
    int Calc(int x, int b){ 
            return ((x+1)/pw[b+1]) * pw[b] + std::min((x+1)%pw[b+1], pw[b]); 
    }
    
    void Work(){
            L = read(), R = read();
            Ans = 0;
            for(reg int b = 0; pw[b] <= R; b ++){ 
                    int num_0 = Calc(R, b) - Calc(L-1, b), num_1 = R-L+1 - num_0;
                    int pluss = (2ll*num_0*num_1 % mod) * pw[b] % mod;
                    Ans = (1ll*pluss + Ans) % mod;
            }
            printf("%d
    ", Ans);
    }
    
    int main(){
            pw[0] = 1;
            for(reg int i = 1; pw[i] <= mod; i ++) pw[i] = pw[i-1] << 1;
            int T = read();
            while(T --) Work();
            return 0;
    }
    
    
  • 相关阅读:
    20180813 mysql 手动整理
    20180811 mysql 整理
    20180810 mysql
    20180808 第一阶段项目展示
    20180807 接近第一阶段项目完成 心里话
    20180730 轮播 (加定时器 鼠标移入停止 移除继续轮播 点击小图标换大图片)
    20180730 表格的删除 增加 编辑内容
    10.10日PHP MAC
    10.09日PHP MAC
    数据库类的封装
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822601.html
Copyright © 2020-2023  润新知