题目链接:
https://codeforces.com/contest/1151/problem/C
题目大意:
一开始第一行是 1,第二行是2 4 ,第三行是3 5 7 9 ,类似这样下去,每一行的个数是上一行的个数,然后对这些点从第一个进行编号,问你从[l,r]区间数的和。
具体思路:
我们可以先求出前l-1个的总和,然后再求出前r个的总和,这两部分做差就是最终答案。
然后具体每一次计算的时候,按照题目描述的求出前n个有多少个奇数,有多少个偶数。
前m个奇数的和是(m^2),前m个奇数的和是(m*(m+1))。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 const int maxn = 2e5+100; 5 const ll mod = 1e9+7; 6 ll solve(ll pos){ 7 ll ans=0; 8 ll num_even=0; 9 ll num_odd=0; 10 int type=0; 11 for(ll i=1;i<=pos;i*=2){ 12 ll num=min(i,pos-ans);// 防止计算最后一块区域的时候算多了 13 ans+=i; 14 if(!type)num_even+=num; 15 else num_odd+=num; 16 type^=1; 17 } 18 num_even%=mod; 19 num_odd%=mod; 20 ans=(num_even*num_even%mod)+(num_odd*(num_odd+1ll)%mod); 21 ans%=mod; 22 return ans; 23 } 24 int main(){ 25 ll l,r; 26 scanf("%lld %lld",&l,&r); 27 ll ans=solve(r)-solve(l-1); 28 while(ans<0)ans+=mod; 29 printf("%lld ",ans); 30 return 0; 31 }