code for 1

2017-08-02 17:23:14

writer:pprp

题意:将n分解为n/2, n%2, n/2三部分,再将n/2分解。。得到一个序列只有0和1,给出[l, r]问l到r有几个1

题解:分治


代码及分析如下:

#include <iostream>

using namespace std;
typedef __int64 ll;

//L,R是查询区间,l,r是计算出的分解以后的长度
ll query(ll L ,ll R,ll l,ll r, ll n) 
{
      if(l == r)
      return n;
      
      //分治
      ll mid = (l+r)>>1;
      ll ans = 0;
      
      //在左侧进行递归
      if(L <= mid - 1)
            ans += query(L,R,l,mid - 1,n>>1);
      //在右侧进行递归查找
      if(R >= mid + 1)
            ans += query(L,R,mid + 1,r,n>>1);
      //这个时候对mid进行处理,判断条件是mid在查询范围区间内
      if(mid <= R && mid >= L)
            ans += n%2;
      
      return ans;
}

//该函数是用来求分解n以后的位数
//也可以看出一个规律,某个数的展开以后的位数是刚好大于二次幂的值减去1,比如3的展开为4-1,4的展开为8-1
ll f(ll n) { if(n == 1 || n == 0) return 1; return 2 * f(n >> 1) + 1; } int main() { ll n; ll l, r; cin >> n >> l >> r; cout << query(l,r,1,f(n),n) << endl; return 0; }
原文地址:https://www.cnblogs.com/pprp/p/7275076.html