​一个传送门​

如 果 我 们 求 出 前 r 个 数 的 和 s 1 , 求 出 前 ( l − 1 ) 个 数 的 和 s 2 如果我们求出前r个数的和s_1,求出前(l-1)个数的和s_2 如果我们求出前r个数的和s1​,求出前(l−1)个数的和s2​

那 么 答 案 就 是 s 1 − s 2 那么答案就是s_1-s_2 那么答案就是s1−s2

那 么 问 题 就 是 考 虑 如 何 求 前 x 个 数 的 和 \color{Red}{那么问题就是考虑如何求前x个数的和} 那么问题就是考虑如何求前x个数的和

看 到 l 和 r 最 大 1 e 18 , 所 以 我 们 可 以 把 这 些 数 字 分 组 ( 最 多 分 64 组 ) 看到l和r最大1e18,所以我们可以把这些数字分组(最多分64组) 看到l和r最大1e18,所以我们可以把这些数字分组(最多分64组)

第 一 组 1 个 数 : 1   ( 1 为 首 相 , 长 为 1 , 公 差 2 ) 第一组1个数:1\ (1为首相,长为1,公差2) 第一组1个数:1 (1为首相,长为1,公差2)

第 二 组 2 个 数 : 2   4   ( 2 为 首 项 , 长 为 2 , 公 差 2 ) 第二组2个数:2\ 4\ (2为首项,长为2,公差2) 第二组2个数:2 4 (2为首项,长为2,公差2)

第 三 组 4 个 数 : 3   5   7   9   ( 3 为 首 项 , 长 为 4 , 公 差 2 ) 第三组4个数:3\ 5\ 7\ 9\ (3为首项,长为4,公差2) 第三组4个数:3 5 7 9 (3为首项,长为4,公差2)

. . . . . . . . . . . . . . . . . . . . . . ...................... ......................

因 为 每 组 数 量 指 数 上 升 , 所 以 最 多 分 64 组 ( 可 能 更 少 ) 因为每组数量指数上升,所以最多分64组(可能更少) 因为每组数量指数上升,所以最多分64组(可能更少)

由 于 每 组 的 第 一 项 容 易 得 到 , 每 组 的 个 数 容 易 得 到 , 根 据 等 差 数 列 求 和 由于每组的第一项容易得到,每组的个数容易得到,根据等差数列求和 由于每组的第一项容易得到,每组的个数容易得到,根据等差数列求和

每 组 的 和 模 后 也 容 易 得 到 。 那 么 我 们 记 录 一 个 前 缀 和 每组的和模后也容易得到。那么我们记录一个前缀和 每组的和模后也容易得到。那么我们记录一个前缀和

找 到 x 最 多 分 到 哪 一 组 , 比 如 x = 5 找到x最多分到哪一组,比如x=5 找到x最多分到哪一组,比如x=5

那 么 最 多 分 到 第 二 组 , 就 加 上 s u m n [ 2 ] , 第 三 组 溢 出 了 2 个 那么最多分到第二组,就加上sumn[2],第三组溢出了2个 那么最多分到第二组,就加上sumn[2],第三组溢出了2个

所 以 再 加 上 以 第 三 组 第 一 个 数 为 首 项 , 长 2 的 等 差 数 列 。 所以再加上以第三组第一个数为首项,长2的等差数列。 所以再加上以第三组第一个数为首项,长2的等差数列。

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll mod=1e9+7;
ll l,r,sumn[67],pre[67];
ll equal(ll x,ll len)//计算以x开头,元素个数len,公差2的和
{
ll q=len%mod,w=(len-1)%mod,sx=x%mod;
return (sx*q%mod+q*w%mod)%mod;
}
ll solve(ll s)
{
ll len=1,he=0,num=0;
for(ll i=1;i<=64;i++)
{
he+=len;
if(he>s) { he-=len;break;}
num=i,len*=2;
}
return (sumn[num]+equal(pre[num+1],s-he))%mod;
}
int main()
{
cin>>l>>r;
ll len=1;
pre[1]=1,pre[2]=2;
for(ll i=1;i<=64;i++)
{
if(i%2==1)//奇数
{
//pre[i]开头的len个奇数
sumn[i]=(sumn[i-1]+equal(pre[i],len));
pre[i+2]=(pre[i]+len%mod*2%mod)%mod;
}
else
{
//pre[i]开头的len个偶数
sumn[i]=(sumn[i-1]+equal(pre[i],len))%mod;
pre[i+2]=(pre[i]+len%mod*2%mod)%mod;
}
len*=2;//每次持续的长度
}
cout<<(solve(r)+mod-solve(l-1))%mod;
}