欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

UPC——喜爱

程序员文章站 2022-03-26 11:34:59
...

这里是引用小s最近对数字情有独钟。他又发现了一种神奇的数字。对于数x,如果它二进制表示中只有一位是0,则x就会被小s所喜爱。比如5,二进制为101,则它被小s所喜爱。
现在,小s想知道,对于一个区间[L,R],有多少数是他所喜爱的。
对于100%的数据:L,R≤1018,T≤10000

题意:求[l,r]范围内二进制只有一位是1的数的个数;

UPC——喜爱
可以看出从2i 到2i+1一共有i个满足题意的数;
用a[i]代表小于2i有多少个满足题意的数,然后根据题目的所给的[l,r]找到满最小的a[l1]>=l,a[r1]>=r,以l1,r1为上下界,然后逐一剔除或这添加满足的数,
可以看到,每一个满足的数,都是从2i+1-2开始,每次递减2k(k=1.2…);

例如[5,10]可以在所给的a中找到满足的区间[8,16];先假设a[4]-a[3]所有的数都满足,然后以8-2=6为起点每次递减2k到5停止,可以找到6 ,5 满足题意加上,然后再以16-2=14为界递减,到10停止,这时候剔除了14 .13 .11,;最后结果就是a[4]-a[3]+2-3=2;

附上自己都看不懂的代码,想像某大佬一样写DP或二分,但是本蒟蒻不会啊。

ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=(ans*a);
        }
        a=(a*a);
        b/=2;
    }
    return ans;
} 
ll a[500];
int main()
{
    a[0]=1;
    ll ans;
        for(ll i=1;i<=200;i++)
        a[i]=a[i-1]+i-1;
        ll t;
        cin>>t;
        ll tp;
        ll l,r,l1,r1,t1,t2;
        while(t--)
        {
            scanf("%lld %lld",&l,&r);
            if(l>r) swap(l,r);
            for(ll i=0;i<=200;i++)
            {
                tp=qpow(2,i);
                if(l<=qpow(2,i))
                {
                     
                    l1=qpow(2,i);
                    t1=i;   
                    break;
                }
            }
            for(ll i=0;i<=200;i++)
            {
                if(r<=qpow(2,i))
                {
                    r1=qpow(2,i);
                    t2=i;
                    break;
                }
            }
            ans=a[t2]-a[t1];
            ll k=0;
 
            for(ll i=l1-2;i>=l;k++)
            {
                ans++;
                i-=qpow(2,k);
            }
             k=0;
            for(ll i=r1-2;i>=r;k++)
            {
                ans--;
                i-=qpow(2,k);
            }
            ll flag=0,ans2;
                while(r)
                {
                    ans2=r%2;
                    r/=2;
                    if(ans2==0)
                        flag++;
                    if(flag==2)
                        break;
                }
                if(flag==1)
                    ans++;
            cout<<ans<<endl;
        }
} ``