Codeforces Round #399 (Div. 1 + Div. 2, combined) B. Code For 1 (递归分治)

版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/82149564

原题地址:http://codeforces.com/problemset/problem/768/B

题意:有一个序列,刚开始,只有 1 个数 n ,接着按照以下顺序变化:
找到序列中任意一个>1的数p,将他变为 p / 2 , p mod 2 , p / 2 直到所有点数都不大于 1 为止。 问最后的序列 区间 [ l , r ] 中有多少个 1

思路:我们可以找规律知道,每一个数字可以分为3部分,其中第一部分和第三部分都是相同的.
那么基于这个规律,我们可以通过递归分治的方法来解决这个问题.

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
ll n, l, r;
ll sum(ll n) {
    ll x = log2(n);
    return (1LL << (x + 1)) - 1;
}
ll query(ll n, ll L, ll R, ll l, ll r) {
    if (l <= L && r >= R) return n;
    if (n == 0) return 0;
    if (R < l) return 0;
    if (L > r) return 0;
    ll mid = (L + R) / 2;
    return query(n / 2, L, mid - 1, l, r) + query(n % 2, mid, mid, l, r) + query(n / 2, mid + 1, R, l, r);
}
int main() {
    scanf("%lld%lld%lld", &n, &l, &r);
    printf("%lld\n", query(n, 1, sum(n), l, r));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/82149564