南邮 OJ 1052 水王争霸

水王争霸

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 171            测试通过 : 79 

比赛描述

       为了丰富校园网络生活,学校 BBS 举行了一次水王争霸赛。比赛开始后,选手们疯狂灌水,都想争取到水王这个荣誉称号。但学校的 BBS 是如此的不堪一击,才 1e-3 秒就超负荷了。
       现在需要把选手们灌的水集合起来,降低服务器负荷。
       事情是这样得到处理的:
       假设每个选手每次灌水量为1L,每灌一次水,服务器就用一个容量为无限的虚拟容器收集这1L水。
       最后服务器中有N个容器收集了水。而服务器最多能负载K个装了水的容器。但是,服务器只有一种自救措施:就是把两个装了同样多水的容器合并到这两个容易中的其中一个,另一个空了的直接free它。
然而不能排除这种情况的存在:通过自救方式,仅由选手们灌好的N容器水不能恰恰好收集成不超过K个非空容器来装。比如,N=3,K=1的时候,无论如何收集,都只能得到容量分别为1L和2L的两个非空容器,不可能得到符合要求的1个非空容器。幸运的是,服务器还有一点点空间,允许你再灌若干次水,使得 BBS 恢复正常。拯救服务器中的虚拟世界这个艰巨而光荣的任务就落到你身上了。


输入

有1000组输入数据,每组输入数据一行,包含两个正整数N、K,其中N不超过10,000,000,K不超过1,000。

输出

输出最少需要继续灌水的次数,如果不可能拯救服务器,输出-1。

样例输入

3 1
13 2
1000000 5
100 100

样例输出

1
3
15808
0

题目来源

wwm





#include<stdio.h>
int bits(int num){
	int nBits=0;
	while(num){
		nBits++;
		num &= (num-1);
	}
	return nBits;
}
int lastOnePos(int num){
	if(num==0){
		return -1;
	}
	int i=0;
	while( (num&1)==0){
		i++;
		num >>= 1;
	}
	return i;
}
int lack(int N, int K){
	int sum=0,addNum;
	while(bits(N)>K){
		addNum = 1<<lastOnePos(N);
		N += addNum;
		sum += addNum;
	}
	return sum;
}
int main(){
	int i,N,K;
	i = 1000;
	while(i--){
		scanf("%d%d",&N,&K);
		printf("%d\n",lack(N,K));
	}
}



/*下面做法的错误在于:最后合理的做法不一定是1110000,也可能是1011000
#include<stdio.h>
int main(){
	int weight[31],result;
	int N,K,i,j,maxBit,totalBit;

	for(j=1,i=0;i<32;i++){
		weight[i] = j<<i;
	}
	for(i=0;i<1000;i++){
		scanf("%d%d",&N,&K);
		for(totalBit=0,maxBit=-1,j=N; j; j>>=1){			//maxBit记录最高有效位
			maxBit++;
			if(j&1){
				totalBit++;
			}
		}
		if(totalBit<=K){
			printf("0\n");
		}else{
			for(j=maxBit,result=0;K--;result+=weight[j--]);	//以当前最高位开始,共K位连续1的数值
			result = result>N ? result : weight[maxBit+1];
			printf("%d\n",result-N);
		}
	}
}
*/






你可能感兴趣的:(ACM,南邮OJ,水王争霸)