码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces484 A. Bits

时间:2018-10-05 13:59:23      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:print   main   set   范围   平移   ORC   +=   ++   namespace   

题目类型:位运算

传送门:>Here<

题意:求区间\([L,R]内二进制中1的个数最多的那个数,如果有多解输出最小解\)

解题思路

想了15min就一遍A了

我们可以贪心地在\(L\)的基础上+1,从小的往大的加。根据二进制的性质,我们不可能把原来的1变成0,除非在更高位搞出一个新的1来。因为如果不在更高位搞出一个1,就肯定比\(L\)小了。而我们又不可能搞掉一个地位,去弄一个高位,因为这样不仅没有让1的个数增多,反而让数字更大了

因此我们的最优策略,就是从最低位开始给0的位补1。知道超过\(R\)为止

反思

贪心思想

Code

注意,\(C++\)中的平移运算符是不可以超过31位的(我就是因为这个调试了很久)。所以在\(long \ long\)范围下2的幂要手打

/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 20010;
const int INF = 1061109567;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline ll read(){
    ll x = 0; int w = 1; register char c = getchar();
    for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
    if(c == '-') w = -1, c = getchar();
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
ll N,l,r,ans,num;
ll power2(ll x){
    ll res = 1;
    for(ll i = 1; i <= x; ++i) res *= 2;
    return res;
}
signed main(){
    N = read();
    for(ll i = 1; i <= N; ++i){
        l = read(), r = read();
        num = 0;
        for(ll j = 0; j < 61; ++j){
            if(l & power2(j)){
                ++num;
            }
        }
        ans = l;
        for(ll j = 0; j < 61; ++j){
            if((!(l & power2(j))) && (ans + power2(j) <= r)){
                ++num;
                ans += power2(j);
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

Codeforces484 A. Bits

标签:print   main   set   范围   平移   ORC   +=   ++   namespace   

原文地址:https://www.cnblogs.com/qixingzhi/p/9744419.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!