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