题目链接:here
对于 n 瓶一升的水,把他们合并后,最少需要的瓶子数为 n 的二进制中 1 的个数。假 设 n 的二进制中 1 的个数大于 k,那么我们要找到 1 个大于 n 的数,且二进制中 1 的个数等 于 k 的最小的数 m,那么答案为 m-n。
假设 n 二进制中,最右边的 1 在第 i 位(这里的第几位是从右往左数的,最右边为第 0 位),那么假设你加上一个小于 2^i 的数,结果二进制中 1 的个数只会增加,如果加上一个 2^i,则结果二进制中 1 的个数必定不会增加。所以只需要一直加上一个 2^i(这里的 i 表示 的是当前水的总体积的二进制中最右边的 1 所在的位置)直到结果中 1 的个数等于 k 即可
1 #include <iostream> 2 #include<cstdio> 3 #define ll long long 4 using namespace std; 5 int cs[100010]; 6 int main() 7 { 8 int t; 9 scanf("%d",&t); 10 int n,k; 11 while(t--) 12 { 13 int ans=0; 14 scanf("%d%d",&n,&k); 15 cs[0]=0; 16 int b=0,cnt=1; 17 while(n) 18 { 19 20 if(n&1) cs[cnt++]=1<<b; 21 n>>=1; 22 b++; 23 } 24 int f=cnt;//杯子 25 for(int i=0;i<cnt&&f>k;i++) 26 { 27 ans+=(cs[i+1]-cs[i]); 28 cs[i+1]<<=1; 29 f--; 30 } 31 printf("%d ",ans); 32 } 33 } 34 35 /************************************************************** 36 Problem: 1228 37 User: yijiull 38 Language: C++ 39 Result: Accepted 40 Time:0 ms 41 Memory:2088 kb 42 ****************************************************************/
很久之前做的了,粘过来~