Codeforces Round #553 (Div. 2) C - Problem for Nazar(数学)

Nazar是一位数学天才,但在老师布置的一道涉及无限数集和复杂数列模式的问题上遇到了挑战。任务是在给定范围内找到一系列按特定模式排列的奇数和偶数之和,并考虑极大的数字范围和模运算。

C. Problem for Nazar
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Nazar, a student of the scientific lyceum of the Kingdom of Kremland, is known for his outstanding mathematical abilities. Today a math teacher gave him a very difficult task.

Consider two infinite sets of numbers. The first set consists of odd positive numbers (1,3,5,7,…), and the second set consists of even positive numbers (2,4,6,8,…). At the first stage, the teacher writes the first number on the endless blackboard from the first set, in the second stage — the first two numbers from the second set, on the third stage — the next four numbers from the first set, on the fourth — the next eight numbers from the second set and so on. In other words, at each stage, starting from the second, he writes out two times more numbers than at the previous one, and also changes the set from which these numbers are written out to another.

The ten first written numbers: 1,2,4,3,5,7,9,6,8,10. Let’s number the numbers written, starting with one.

The task is to find the sum of numbers with numbers from l to r for given integers l and r. The answer may be big, so you need to find the remainder of the division by 1000000007 (109+7).

Nazar thought about this problem for a long time, but didn’t come up with a solution. Help him solve this problem.

Input
The first line contains two integers l and r (1≤l≤r≤1018) — the range in which you need to find the sum.

Output
Print a single integer — the answer modulo 1000000007 (109+7).

Examples
inputCopy
1 3
outputCopy
7
inputCopy
5 14
outputCopy
105
inputCopy
88005553535 99999999999
outputCopy
761141116
Note
In the first example, the answer is the sum of the first three numbers written out (1+2+4=7).

In the second example, the numbers with numbers from 5 to 14: 5,7,9,6,8,10,12,14,16,18. Their sum is 105.

解析

找出前x个数最大的奇数和最大的偶数就能求和了,然后用fi®-fi(l-1)即可
需要注意的是由于数字很大,非常容易爆long long 所有在循坏中写的是x-=num,而不是用sum纪录总共有了几个数字,这一点卡的我心态爆炸。。

code

#include<bits/stdc++.h>
#define pb push_back
#define ll long long
using namespace std;
const int N=3e5+10;
int mod=1e9+7;
ll pow(ll x,ll n){
    ll ans=1;
    while(n){
        if(n&1){
            ans=ans*x%mod;
        }
        x=x*x%mod;
        n>>=1;
    }
    return ans;
}
ll fi(ll x){
    if(x<2){
        return x;
    }
    ll odd=1,even=0,num=2,pp=1;
    x--;
    ll now1=0,now2=0;
    ll c=2;
    while(x){
        if(x<num) num=x;
        if(pp){
            even=(even+num*2%mod)%mod;
        }
        else {
            odd=(odd+num*2%mod)%mod;
        }
        x-=num;
        num*=2;
        pp=!pp;
    }
    now1=odd,now2=even;
    ll ans=((now1-1)%mod*pow(c,mod-c)%mod+1)%mod*(1+now1)%mod*pow(c,mod-c)%mod;
    ans+=((now2-2)%mod*pow(c,mod-c)%mod+1)%mod*(2+now2)%mod*pow(c,mod-c)%mod;
    return ans%mod;
}
int main()
{
    #ifdef local
        freopen("D://r.txt","r",stdin);
    #endif
    ll l,r;
    cin>>l>>r;
    //cout<<fi(r)<<' '<<fi(l-1)<<endl;
    cout<<((fi(r)-fi(l-1))%mod+mod)%mod<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值