zoukankan      html  css  js  c++  java
  • 异或

    也许更好的体验
    (mathcal{Description})

    给定L,R,求
    (sum_{i=L}^{R}xorsum_{i=L}^{R})
    答案对1000000007取模
    (L,R<=10^9)
    (mathcal{Solution})

    对于有异或的题目要记住这点
    每个二进制位是独立计算答案的
    我们只需知道([L,R])中所有数在每个位上的情况:有多少(0)多少(1)
    只有(1)^(0)的结果为(1),统计出每个为上的(1)(0)的个数,用当前位的值乘以(1)的个数再乘以(0)的个数即可
    对于每个二进制位上的0和1出现情况
    如第(3)
    000
    001
    010
    011
    100
    101
    110
    111
    (2^4)出现(2^3)(0)(1)
    不难发现每(2^{n+1})个数在第n位出现(2^n)(0)(1)
    由于对数会被异或两次 i^j j^i,所以计算时要乘以(2)
    (ans=(ans+2*zero[i]*one[i]*2^i)%mod;)
    其中(mi[i]=2^i)
    (0)(1)的计算
    用一个简单的容斥即可
    对于第n位
    R中包含的(2^{n+1})的个数减去L中包含的(2^{n+1})个数加上(R\%2^{n+1})中的个数减去(L\%2^{n+1})中的个数
    注意起点为(0),即求的区间是([0,R]-[0,L-1])
    处理看代码吧

    /*******************************
    Author:Morning_Glory
    LANG:C++
    Created Time:2019年06月10日 星期一 07时59分11秒
    *******************************/
    #include <cstdio>
    #include <fstream>
    #include <cstring>
    using namespace std;
    const int mod = 1000000007;
    const int maxn = 55;
    int n,T,t,l,r;
    long long ans;
    long long zero[maxn],one[maxn],mi[maxn];
    int main()
    {
    	scanf("%d",&T);
    	mi[0]=1;
    	for (int i=1;i<=31;++i)	mi[i]=mi[i-1]<<1;
    	while (T--){
    		scanf("%d%d",&l,&r);
    		memset(one,0,sizeof(one));
    		memset(zero,0,sizeof(zero));
    		ans=0;
    		for (int i=0;mi[i]<=r;++i){
    			one[i]=((r+1)/mi[i+1]-l/mi[i+1])*mi[i];//R中包含的2^{n+1}的个数减去L中包含的2^{n+1}个数
    			zero[i]=one[i];
    			//加上R%2^{n+1}中的个数
    			if (r+1>mi[i+1]){
    				t=(r+1)%mi[i+1];
    				if (t>mi[i])	one[i]+=t-mi[i],zero[i]+=mi[i];
    				else	zero[i]+=t;
    			}
    			else if (r+1<mi[i+1]){
    				if (r+1>mi[i])	one[i]+=r+1-mi[i],zero[i]+=mi[i];
    				else	zero[i]-=r+1;
    			}
    			//减去L%2^{n+1}中的个数
    			if (l>mi[i+1]){
    				t=l%mi[i+1];
    				if (t>mi[i])	one[i]-=t-mi[i],zero[i]-=mi[i];
    				else	zero[i]-=t;
    			}
    			else if (l<mi[i+1]){
    				if (l>mi[i])	one[i]-=l-mi[i],zero[i]-=mi[i];
    				else	zero[i]-=l;
    			}
    			ans=(ans+2ll*zero[i]*one[i]%mod*mi[i])%mod;
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何查看ipynb文件
    使用python绘制爱心
    使用python将十进制数转为ip地址
    python使用下划线分割数字,提高可读性
    python的字符串基本操作
    pandas为csv添加新的行和列
    使用pandas库实现csv行和列的获取
    pycharm批量更改变量名
    (转)Doxygen文档生成工具
    MVC架构学习之Smarty学习——病来而蔫
  • 原文地址:https://www.cnblogs.com/Morning-Glory/p/11011334.html
Copyright © 2011-2022 走看看