一天,CC買了N個容量能夠認爲是無限大的瓶子,開始時每一個瓶子裏有1升水。接着~~CC發現瓶子實在太多了,因而他決定保留不超過K個瓶子。每次他選擇兩個當前含水量相同的瓶子,把一個瓶子的水所有倒進另外一個裏,而後把空瓶丟棄。(不能丟棄有水的瓶子)c++
顯然在某些狀況下CC沒法達到目標,好比N=3,K=1。此時CC會從新買一些新的瓶子(新瓶子容量無限,開始時有1升水),以到達目標。數組
如今CC想知道,最少須要買多少新瓶子才能達到目標呢?ui
輸入格式:spa
一行兩個正整數, N,K(1\le N\le 2\times 10^9,K\le 10001≤N≤2×109,K≤1000)。code
輸出格式:get
一個非負整數,表示最少須要買多少新瓶子。數學
輸入樣例#1:it
3 1io
輸出樣例#1:class
1
輸入樣例#2:
13 2
輸出樣例#2:
3
輸入樣例#3:
1000000 5
輸出樣例#3:
15808
這道題要麼你須要對很好的數學思惟(能夠一眼看出),要麼你就須要舉例子
蒟蒻固然是選擇第二種
如下咱們列出每一行的第一個數爲最開始的瓶子個數,第二行爲合併後最少的瓶子個數,第二個數爲它合併前的瓶子個數的二進制
1 1 0001 2 1 0010 3 2 0011 4 1 0100 5 2 0101 6 2 0110 7 3 0111 8 1 1000 ...
咱們發現合併後的瓶子個數就是合併前瓶子個數的二進制下1的個數,如今問題就轉化成了如何求出一個數的二進制下1的個數
暴力求會T,那麼怎麼快速求出呢?
樹狀數組都會吧,還記得\(lowbit(x)\)?咱們能夠用\(x\&-x\)求出一個數從後往前數第一個1的位置,就用這個來求
#include<bits/stdc++.h> #define in(i) (i=read()) #define il extern inline #define rg register #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define lol long long using namespace std; const int N=1e7+10; int read() { lol ans=0, f=1; char i=getchar(); while (i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();} while (i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48), i=getchar(); return ans*f; } int lowbit(int x) {return x&-x;} int cal(int x,int ans=0) { while(x) x-=lowbit(x),ans++; return ans; } int main() { int n,k,ans=0; in(n), in(k); while(cal(n)>k) ans+=lowbit(n),n+=lowbit(n); cout<<ans<<endl; }