codeforces 768 B. Code For 1(二分)

题目链接:http://codeforces.com/contest/768/problem/B

题意:给你一个数n和区间l,r,每次都能把任意数拆成n/2,n%2,n/2三个数,直到变成0和1,问区间l,r里有多少个1

 

题解:明显最后生成的是对称的,所以只要考虑一半就行,但是这里的n,l,r很大,有2的50次,最后起码有2的50

次长所以dfs直接生成字符串是不行的也会超时,但是r-l才10的5次所以可以考虑一下二分。加上这题的对称,二分很

方便。

附上二分的代码。二分的是位置,l到r之间的位置,mid值是num对应的中间值,然后取什么就看num%2是什么即可。

void binsearch(long long le , long long ri , long long num) {

    long long mid = (le + ri) >> 1;

    if(ri < l || le > r || le > ri)//注意要有le>ri退出,这很关键也是二分退出的条件。

        return ;

    if(mid < l) {

        binsearch(mid + 1 , ri , num / 2);

    }

    else if(mid > r) {

        binsearch(le , mid - 1 , num / 2);

    }

    else {

        ans += num % 2;

        binsearch(le , mid - 1 , num / 2);

        binsearch(mid + 1 , ri , num / 2);

    }

}

#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
string s , sl;
long long n , l , r , ans;
long long dfs(long long num) {
    if(num == 1) {
        return 1;
    }
    return 1 + 2 * dfs(num / 2);
}
void binsearch(long long le , long long ri , long long num) {
    long long mid = (le + ri) >> 1;
    if(ri < l || le > r || le > ri)
        return ;
    if(mid < l) {
        binsearch(mid + 1 , ri , num / 2);
    }
    else if(mid > r) {
        binsearch(le , mid - 1 , num / 2);
    }
    else {
        ans += num % 2;
        binsearch(le , mid - 1 , num / 2);
        binsearch(mid + 1 , ri , num / 2);
    }
}
int main() {
    cin >> n >> l >> r;
    if(n == 0) {
        cout << 0 << endl;
        return 0;
    }
    long long count = dfs(n);
    binsearch(1 , count , n);
    cout << ans << endl;
    return 0;
}
posted @ 2017-04-12 17:40  Gealo  阅读(463)  评论(0编辑  收藏  举报