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;
}