奇偶性质+快速乘
hint:真的太菜了,昨天个人训练赛的时候憋了三个小时,还是没推出来,B题和D题连读都没读,感觉应该能做的,但一心想把这个数学题做出来,,最后直接憋死了。哎,还是要继续努力鸭。
题意:存在一个按顺序存储无限多个偶数的集合和一个按顺序存储奇数的集合,则存在一个数k=0,先在奇数集合中取1<<k个数,k++,然后再从偶数集合中取1<<k个数,k++,之后循环此操作。即可得到一个序列。现有long long int 范围内的两个数l,r;求上述序列中l与r下标之间的数的sum。
正解:前n个奇数的sum=n x n,前n个偶数的sum=n x n+1;则统计前l-1和前r个数中奇数和偶数的个数,求sum后做差即可得到ans;
注意,n*n会爆long long int,故须采用快速乘来求解。
AC代码如下:
#include <bits/stdc++.h>
#define FOPI freopen("INPUT.TXT", "r", stdin)
#define DOPI freopen("OUTPUT.TXT", "w", stdout)
#define FOR(i, x, y) for(int i = x; i <= y; i ++)
#define ROF(i, x, y) for(int i = x; i >= y; i --)
using namespace std;
typedef long long int ll;
const int ind=0x3f3f3f3f,N=1e6+10;
const ll inlld=0x3f3f3f3f3f3f3f3f,mod=1e9+7;
ll mul(ll a,ll b)
{
ll ans=0;
while(b){
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
ll getans(ll a)
{
ll num=0,odd=0,even=0;
while(a>0){
if(!(num%2))odd+=min(a,(ll)1<<num);
else even+=min(a,(ll)1<<num);
// num++;
a-=(ll)1<<num;
num++;
}
return (mul(odd,odd)+mul(even,even+1)+mod)%mod;
}
int main()
{
ios::sync_with_stdio(false);
ll l,r;cin>>l>>r;
cout <<(getans(r)-getans(l-1)+mod)%mod<<endl;
return 0;
}
/*
88005553535 99999999999
761141116
5 14
105
1 3
7
*/