B-Code For 1 Codeforces 768【递归】 好题!

题意:起初,序列中仅有数n,if(n!=0 && n!=1) 在原来的位置补充3个元素n/2 n/%2 n/2 。 直至该序列用仅有0和1。现在问区间[l,r]有多少个1

思路:一开始想用vector模拟,感觉实现起来很麻烦,很繁琐。 去网上看了题解,首先要求出对于当前的n,一共能拆分成多少个元素(仅为0和1),那么区间长度就是[1,len]确定下来。接着去枚举每一个位置的值是0还是1(递归)。

数据分析:0 ≤ n < 250, 0 ≤ r - l ≤ 105, r ≥ 1, l ≥ 1

复杂度分析:递归层数最多150层

// 很少做递归的题,这题也是看了题解才会的

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll ans=0;

void query(ll n,ll l,ll r,ll nl,ll nr)
{
    if(nr<l || nl > r || n==0)  return ;
    if(n==1)
    {
        //cout << "woc" << endl;
        ans++;
        return ;
    }
    ll mid=l+r >> 1;
    //对于当前n,我们去判断n/2,n%2,n/2 的情况
    query(n/2,l,mid-1,nl,nr);
    query(n%2,mid,mid,nl,nr);
    query(n/2,mid+1,r,nl,nr);
}

int main(void)
{
    ll n,l,r;
    cin >> n>> l>> r;
    ll len=1,n1=n;
    while(n1>1)
    {
        len=len*2+1;//左右对称*2,每次多个%2,+1
        n1/=2;
    }
    query(n,1,len,l,r);//递归
    cout << ans << endl;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值