zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:异或(数学)

    题目描述

    给定$L,R$,我们希望你求出:
    $$sumlimits_{i=L}^Rsumlimits_{j=L}^R(ioplus j)$$
    其中这里的$oplus$表示异或运算。
    答案对$10^9+7$取模。


    输入格式

    第一行一个整数$T$,表示数据组数。
    接下来$T$行,每行两个整数$L,R(0leqslant Lleqslant Rleqslant 10^9)$,描述一组数据。


    输出格式

    每组数据输出一行一个整数,表示答案。


    样例

    样例输入:

    2
    1 2
    0 1023

    样例输出:

    6
    536346624


    数据范围与提示

    样例解释:

    第一组数据:$1oplus 1=2oplus 2=0,1oplus 2=3$。

    数据范围:

    对$100\%$的数据,$Tleqslant 50$。
    $ullet$子任务$1$($20$分):保证$L,Rleqslant 1,000$。
    $ullet$子任务$2$($30$分):保证$(R−L)leqslant 10^6$。
    $ullet$子任务$3$($10$分):保证$L=0,R=2^k−1$。
    $ullet$子任务$4$($40$分):无特殊限制。


    题解

    又没打正解,讲一下我的做法。

    其实答案就是二进制位下每一位$1$的个数乘每一位$0$的个数乘$1<<$当前位数。

    那么考虑如何快速求出每一位$1$和$0$的个数。

    把每一个数拆成二进制位,如下$downarrow$

    0:0000
    1:0001
    2:0010
    3:0011
    4:0100
    5:0101
    6:0110
    7:0111

    那么我们会惊喜的发现第$i$位会呈一个$2 imes i$的循环节,先是$i$个$0$,之后是$i$个$1$。

    算出$0sim R$中$0$和$1$的个数再减去$0sim L$的即可,这样就能算出每一位$0$和$1$的个数了,也就求出了答案。

    时间复杂度:$Theta(30 imes T)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1000000007;
    long long L,R;
    long long ans;
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		ans=0;
    		scanf("%lld%lld",&L,&R);
    		for(long long i=1;i<=30;i++)
    		{
    			long long flag=(R/(1<<i)-(L-1)/(1<<i))<<(i-1);
    			if(R%(1<<i)-(1<<(i-1))+1>0)flag+=R%(1<<i)-(1<<(i-1))+1;
    			if((L-1)%(1<<i)-(1<<(i-1))+1>0)flag-=(L-1)%(1<<i)-(1<<(i-1))+1;
    			ans=(ans+flag*(R-L+1-flag)%mod*(1<<i)%mod)%mod;
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    oracle中 connect by prior 递归算法
    sql优化__rownum的使用【转】
    ASP.NET Core四大部件
    .net core Socket
    .NET Core 配置文件
    .NET Core IOC AOP
    Quartz.Net—MisFire
    Quartz.Net—配置化
    Quartz.Net—IJob特性
    Quartz.Net—DateBuilder
  • 原文地址:https://www.cnblogs.com/wzc521/p/11743461.html
Copyright © 2011-2022 走看看