2019.5.11 海淀區賽之杯子

lqxssf發表於2019-05-11

emmmm區賽唯一一道ac的題


題目描述
小明買了N個容積可以是無窮大的杯子,剛開始的時候每個杯子裡有1升水, 接著小明發現杯子實在太多了,於是他決定保留不超過K個杯子。每次他選擇兩 個當前含水量相等的杯子,把一個杯子的水全部倒進另一個裡,然後把空瓶丟棄。
(不能丟棄有水的杯子) 顯然在有些情況下小明無法達到他的目標,比如N=3,K=1。此時小明會重
新買一些新的杯子(新杯子容積無限,開始時有1升水),以達到目標。 現在小明想知道,最少需要買多少個新杯子才能達到目標呢?
輸入
一行兩個正整數,N,K(1≤N≤1000000000,K≤1000)。
輸出
一個非負整數,表示最少需要買多少新杯子。
樣例輸入
1000000 5
樣例輸出
15808
提示
【資料範圍】
對於50%的資料,N≤10000000; 對於100%的資料如題目。

經過模擬 我們很容易發現 杯子內的水從1到2到4的過程很像2進位制的加減法有沒有??
所以大致思路就是 把n轉化成2進位制 某一位上為1說明存在一個杯子內有該位表示的數這麼多的水
也就是說 n的二進位制表示n的最後狀態
我們只需要從後往前數k位 記錄該位表示的數為cnt 通過將前面所有的數加一些1變為cnt即可
#include<iostream>
using namespace std;
long long n,k,a[100005],idx,cnt,flag,flag1;
int main()
{
    scanf("%lld%lld",&n,&k);
    int tmp=n;
    while(tmp>0)
    {
        a[++idx]=tmp%2;
        tmp/=2;
    }
    for(long long i=1;i<=idx;i++)
        if(a[i])cnt++;
    if(cnt<=k)
    {
        putchar('0');
        return 0;
    }
    long long cnt1=0;
    for(long long i=idx;i>=1;i--)
    {
        if(a[i])cnt1++;
        if(cnt1==k)
        {
            flag=i-1;
            flag1=1;
            for(long long j=2;j<=i;j++)flag1*=2;
            break;
        }
    }
    cnt1=0,tmp=1;
    for(long long i=1;i<=flag;i++)
    {
        cnt1+=a[i]*tmp;
        tmp*=2;
    }
    printf("%lld",flag1-cnt1);
    return 0;
}

 

相關文章