个人赛C补题

E - Envious Exponents 题目链接
题目意思:给定两个数n和k,找出大于n的,二进制表示有k个1的最小数。
思路:分类讨论,n的二进制中1的个数与k的关系。

#include<bits/stdc++.h>
#define int long long int
#define r(x) scanf("%lld",&x)
using namespace std;

const int N = 70;
int n, k, a[N], cnt, res;
//cnt表示数组的元素个数,res表示数组中有多少个1
bool flag;

int rst(int x){ //二进制转十进制模拟
    int y = 1, sum = 0;
    if(a[1] == 1) sum = 1;
    for(int i = 2; i <= x; i++){
        y = y * 2;
        if(a[i] == 1)
        sum += y;
    }
    return sum;
}

signed main(){
    r(n), r(k);
    int m = n;
    //把十进制转成二进制
    while(m > 0){
        cnt ++;
        a[cnt] = m % 2;
        if(a[cnt] == 1) res ++;
        m = m / 2;
    }
    //分类讨论数组中1的个数res与k的关系
    if(res < k){
        for(int i = 1; i <= 70; i++){
            if(a[i] == 0){
                a[i] = 1;res ++;
            }
            if(res == k) break;
        }
        res = max(res,cnt);//非常重要,刚开始没写,wa了一发
        cout << rst(res); return 0;
    }
    if(res == k){
       int j, t;
       //找出数组中的第一个1,和1前面的第一个0
       for(j = 1; j <= cnt; j++){
            if(a[j] == 1){
                break;
            }
       }
       for(t = j + 1; t <= cnt; t ++){
            if(a[t] == 0) break;
       }
       swap(a[t],a[j]);
       reverse(a + 1, a + t);
       t = max(t, cnt);
       cout << rst(t);
       return 0;
    }
    if(res > k){
        for(int i = 1; i <= cnt; i++){ //删除数组中多余的1
            if(a[i] == 1){
                a[i] = 0; res --;
            }
            if(res == k) break;
        }
        int i, j;
        for(i = 1; i <= cnt; i++){ 
            //找出剩余数组中的第一个1,和1前面的第一个0,交换
            if(a[i] == 1) break;
        }
        for(j = i + 1; j <= cnt+1; j++){
            if(a[j] == 0) break;
        }
        swap(a[i],a[j]);
        int t = max(j,cnt);
        int num = 0;
        //将剩余的1都安排在低位
        for(int i = 1; i <= j - 1; i ++){
            if(a[i] == 1) {
                a[i] = 0; num ++;
            }
        }
        for(int i = 1; i <= j -1; i++){
            if(num == 0) break;
            a[i] = 1; num --;
        }
        cout << rst(t);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值