E - Envious Exponents 二进制+思维

题目: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;
}

猜你喜欢

转载自blog.csdn.net/YingShen_xyz/article/details/112787948