Envious Exponents 二進制

4897: Envious Exponents

時間限制: 1 Sec  內存限制: 128 MB
提交: 306  解決: 49
[提交] [狀態] [討論版] [命題人:admin]php

題目描述c++

Alice and Bob have an integer N. Alice and Bob are not happy with their integer. Last night they went to a cocktail party and found that another couple had the exact same integer! Because of that they are getting a new integer.

Bob wants to impress the other couple and therefore he thinks their new integer should be strictly larger than N.
Alice herself is actually fond of some specific integer k. Therefore, Alice thinks that whatever integer they pick, it should be possible to write it as a sum of k distinct powers of 2.

Bob is also a cheapskate, therefore he wants to spend as little money as possible. Since the cost of an integer is proportional to its size, he wants to get an integer that is as small as possible.數組

 

輸入app

• A single line containing two integers N and k, with 1 ≤ N ≤ 1018 and 1 ≤ k ≤ 60.函數

 

輸出工具

Output M, the smallest integer larger than N that can be written as the sum of exactly k distinct powers of 2.ui

 

樣例輸入spa

1 2

 

樣例輸出code

3

 

來源/分類blog

BAPC2017 Preliminaries 

 

[提交] [狀態]

這題,調代碼調到完全自閉,而後更自閉的事情是,是函數用錯了,其餘地方都沒bug

題意:給數n和k,求使一個最小的大於n的數m,使m = 2^{a} + 2^{b} + \cdots \cdots(k個2的冪次數相加,且冪次各不相同)

這個題若是找對方向,就很快能寫出來,可是沒有的話,就很難辦了(顯然咱們的方向找的太慢了)

用二進制的思想,將n二進制中的1和k比較,進行加1或減1的操做,就行了

代碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn=100;
typedef  long long ll;
int a[maxn];

int main(){
    ll n,k;
    scanf("%lld%lld",&n,&k);
    ll nn = n;
    int z = 0;
    int q=0;
    while(nn != 0){
        a[z++] = nn % 2;
        if(nn%2==1) q++;
        nn /= 2;
    }
    if(q < k){
        for(int i=0; ; i++){
            if(q == k)  break;
            if(a[i]==0){
                a[i]=1;
                q++;
                if(i>=z){
                    z++;
                }
            }
        }
    }
    else{
        int v = q - k;
        for(int i=0; i<z && v>0; i++){
            if(a[i]==1){
                a[i]=0;
                v--;
            }
        }
        int p = -1;
        for(int i=0; i<z; i++){
            if(a[i]==1 && a[i+1]==0){
                p = i+1;
                break;
            }
        }
        if(p==z){
            memset(a,0,sizeof(a));
            a[z++]=1;
            int t = k-1;
            for(int i=0; i<z && t>0; i++){
                a[i]=1;
                t--;
            }
        }
        else{
            a[p]=1;
            q = k+1;
            for(int i=0; i<p; i++){
                if(a[i]==1){
                    a[i]=0;
                    q--;
                }
            }
            int ss = k - q;
            for(int i=0; i<p && ss>0; i++){
                a[i]=1;
                ss--;
            }
        }
    }
    ll ans = 0;
    for(int i=0; i<z; i++){
        if(a[i]==1)
            ans += (1ll << i);
    }
    printf("%lld\n",ans);
    return 0;
}

左邊的大佬計算了數據,發現最大位數不會超過60,因而數組的邊界就不用維護了,減小了不少麻煩(可能出現的bug)

還有把十進制轉換爲二進制的寫法

我得改改了

for(int i=0; i<61; i++){
    if(n & (1ll << i))
        a[i] = 1;
    else 
        a[i] = 0;
}

還有右邊大佬的代碼,用了一個bitset ,直接存二進制的STL工具

直接上代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int k;
unsigned long long a;
bitset<64> ans;
int main()
{
    cin>>a>>k;
    ans=a;
    if(ans.count()<k)
    {
        k-=ans.count();
        while(k--) a=a|(a+1);
        cout<<a<<endl;
    }
    else
    {
        int cou=ans.count()-k,j=0;
        bool flag=0;
        for(int i=0; i<64; i++)
        {
            if(ans[i])
            {
                if(!cou && !flag) flag=1;
                else if( flag) ans.set(j++);
                else if(!flag) cou--;
                ans.reset(i);
            }
            else if(flag)
            {
                ans.set(i);
                break;
            }
        }
        cout<<ans.to_ulong()<<endl;
    }
    return 0;
}

最後,說說出錯的那個函數__builtin_popcount

用來計算一個數二進制位下有多少個1

聽起來是沒有錯,但是

之後仍是多瞭解瞭解再用。

相關文章
相關標籤/搜索