题目:https://vjudge.z180.cn/contest/417619#problem/E
题意:给你一个数n和k, 然后把它变成k个2的不同幂的和,并且大于n。
分析: 把这个数转化成二进制,然后分情况讨论;
1 cnt < k 时, 只需从低位到高位的0变1即可
2 cnt == k 时, 先把这个数变大(可能cnt有变换),再变成 cnt = k(意思就是必须执行一次改变)
3 cnt > k 时, 从低位找到第一个1前面的0, 将0变1, 然后将变1的这一位的所有低位变成0, such as: 10010, 变成 10100
代码:
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e5 + 50;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int a[N];
ll n, k, m;
inline void Solve(int cnt, bool flag)
{
if (cnt == k && flag) {
return;
}
if (cnt < k) {
for (int i = 1; cnt < k; i++) {
if (a[i] == 0) {
a[i] = 1;
cnt++;
}
if (i > m) m++;
}
} else {
bool flag = false;
for (int i = 1; ; i++) {
if (a[i] == 1) flag = true;
if (a[i] == 0 && flag == true) {
a[i] = 1;
cnt++;
if (i == m + 1) m++;
for (int j = i - 1; j >= 1; j--) {
if (a[j] == 1) {
cnt--;
a[j] = 0;
}
}
break;
}
}
// for (int i = 1; i <= m; i++) cout << a[i];
// cout << endl;
Solve(cnt, 1);
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> k;
int cnt = 0;
while (n) {
a[++m] = n % 2;
if (n % 2) cnt++;
n /= 2;
}
Solve(cnt, 0);
ll ans = 0, indx = 1;
for (int i = 1; i <= m; i++) {
ans += a[i] * indx;
indx *= 2;
}
cout << ans << endl;
return 0;
}