hdu 1538 A Puzzle for Pirates (海盗分金问题)

A Puzzle for Pirates

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 884    Accepted Submission(s): 337


Problem Description
A bunch of pirates have gotten their hands on a hoard of gold pieces and wish to divide the loot. They are democratic pirates in their own way, and it is their custom to make such divisions in the following manner: The fiercest pirate makes a proposal about the division, and everybody votes on it, including the proposer. If 50 percent or more are in favor, the proposal passes and is implemented forthwith. Otherwise the proposer is thrown overboard, and the procedure is repeated with the next fiercest pirate.
All the pirates enjoy throwing one of their fellows overboard, but if given a choice they prefer cold, hard cash, the more the better. They dislike being thrown overboard themselves. All pirates are rational and know that the other pirates are also rational. Moreover, no two pirates are equally fierce, so there is a precise pecking order — and it is known to them all. The gold pieces are indivisible, and arrangements to share pieces are not permitted, because no pirate trusts his fellows to stick to such an arrangement. It's every man for himself. Another thing about pirates is that they are realistic. They believe 'a bird in the hand is worth two in the bush' which means they prefer something that is certain than take a risk to get more, where they might lose everything.

For convenience, number the pirates in order of meekness, so that the least fierce is number 1, the next least fierce number 2 and so on. The fiercest pirate thus gets the biggest number, and proposals proceed in the order from the biggest to the least.

The secret to analyzing all such games of strategy is to work backward from the end. The place to start is the point at which the game gets down to just two pirates, P1 and P2. Then add in pirate P3, P4, ... , one by one. The illustration shows the results when 3, 4 or 5 pirates try to divide 100 pieces of gold.



Your task is to predict how many gold pieces a given pirate will get.
 

Input
The input consists of a line specifying the number of testcases, followed by one line per case with 3 integer numbers n, m, p. n (1 ≤ n ≤ 10^4) is the number of pirates. m (1 ≤ m ≤ 10^7) is the number of gold pieces. p (1 ≤ p ≤ n) indicates a pirate where p = n indicates the fiercest one.
 

Output
The output for each case consists of a single integer which is the minimal number of gold pieces pirate p can get. For example, if pirate p can get 0 or 1 gold pieces, output '0'. If pirate p will be thrown overboard, output 'Thrown'.
 

Sample Input
  
  
3 3 100 2 4 100 2 5 100 5
 

Sample Output
  
  
0 1 98
Hint
Hint
The situation gets complicated when a few gold pieces were divided among many pirates.
 

Author
Otter
 

Source


题解:海盗分金问题
题目大意:有n个海盗,分配m枚金币,海盗依次编号为1... n
然后海盗按照n,n-1,n-2,... 1的顺序提出分配方案, 对于提出的方案进行投票,如果有一半或者一半以上的海盗赞成这个方案(提出方案的海盗也会参与投票),那么久按照这个方案分配金币,否则这个提出方案的海盗就会被扔下船去。每个海盗都绝对聪明,他们会奉行三个标准:保命,拿更多的金子,杀人,三个标准的优先级递减。问编号为p的海盗最后会获得多少个金币(当有多个可能时输出最少的金币数,如果一定会死就输出Thrown)

这是一个非常有趣的问题。

我们还是先从比较简单的例子入手,顺便找找规律。。。

如果只有两个人,那么2号可以得到全部金子,因他自己一定会支持自己,1/2的人支持,方案通过

如果有三个人,假设3号提出的方案不通过,那么1,2号就会面对上面的局面,最终1会一个金子也得不到,所以3号在分配方案的时候,只有拿出一个金子给1号,就可以得到剩余的金子

如果有四个人,假设4号死了,就会回到上面的状态,在上面的状态中2号是得不到金子的,那么4号想让方案通过,只需要用一个金子贿赂2号即可。

如果有5个人,那么5号只需要贿赂上面状态中没有得到金子的1,3号即可。

。。。。。

所以我们发现,如果n号想要保命并且得到金子的话,就要贿赂前面与他奇偶性相同的所有海盗。这是金子数量足够的情况,如果金子不够贿赂前面的海盗呢?

我们还是举例分析一下吧

假设目前有100个金子。

201号海盗,前面与201奇偶性相同的海盗有100个,100+1正好一个金子也得不到,但是可以保命。(刚开我们在纠结一个问题,就是既然金子不够分,那么为什么编号小的海盗不合力将编号大的海盗扔下船呢?因海盗都是绝对聪明的,如果一直持续进行下去,那么海盗们肯定会希望扔下船的越多越好,这样每个人分到的也越多。但是最终剩下两个人的时候,1号就什么都得不到了,而如果他支持3号的方案,那么3号就不会被扔下船,他还可以得到1个金币。所以上述情况不会出现)

202号海盗,自己不拿金币,用100个金币贿赂上一轮没有得到金币的101个海盗中的100个即可(其实就是奇偶性相同的,当然201号自己分的时候得不到金币,贿赂他也一样),(100+1)/202=1/2 可以保命

203号海盗,需要102个人的支持,显然加上他自己,还需要101票,而金子不够贿赂,别人会反对,而达到杀人的目的。

204号海盗,因为如果204号海盗死了,那么203号分金子的时候也必死无疑,所以他一定会无偿的支持204号,那么204号用100个金子去贿赂100个海盗,然后加上203和204自己这两票,正好1/2

205号海盗,需要103个人的支持,金子不够,只能被扔下船。

206号海盗,需要103个人的支持,可以贿赂100个人,205和他自己也会支持,但是还是不够1/2

207号海盗,需要104个人的支持,可以贿赂100个人,205,206,207都会支持,但是还是不够

208号海盗,可以无偿得到205,206,207,208的支持,再贿赂100人就能到达1/2方案集合通过。

依次类推我们会发现规律,就是2*m+2^k(k>0)号海盗虽然分不到金子但是可以保命,可以得到合法的分金子的方案。

如果当前的海盗是介于2*m+2^(k-1)到2*m+2^k之间的,那么这些海盗如果轮到他们分金子,那么他们必死无疑,所以他们一定会支持2*m+2^(k-1)号海盗的分金方案。而剩下的海盗有贿赂和被贿赂两种可能,题目中说输出最小的金子数,那么就是0.

为什么2*m+2^k(k>0)号海盗可以保命呢?因为他可以无偿得到2^(k-1)-1个人(就是那些轮到他们分必死的海盗)的支持,然后可以贿赂m个人,加上自己的一票m+2^(k-1)=1/2(2*m+2^k),所以可以保命。

如果最先分的海盗是必死的,那么知道下一个满足2*m+2^k的人才能分金,那些大于2*m+2^k的人只能被扔下船啦。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,p,t,mi[20];
void solve(int n,int m,int p)
{
	if (n<=2*m) {
		int cnt=m-(n-1)/2;
		if (p==n) {
			printf("%d\n",cnt);
			return;
		}
		if ((p&1)==(n&1)) printf("1\n");
		else printf("0\n");
		return;
	}
	if (n==2*m+1){
	 if (p<2*m&&p&1) printf("1\n");
	 else printf("0\n");
	 return;
    }
    int t=n-2*m;
    for (int i=1;i<=15;i++)
     if (t==mi[i]) {
     	printf("0\n");
     	return;
	 }
	for (int i=1;i<=15;i++)
	 if (t<mi[i]) {
	 	if (p>2*m+mi[i-1]&&p<2*m+mi[i]) printf("Thrown\n");
	 	else printf("0\n");
	 	return;
	 }
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("my.out","w",stdout);
    scanf("%d",&t);
    mi[0]=1;
    for (int i=1;i<=15;i++) mi[i]=mi[i-1]*2;
	for (int i=1;i<=t;i++) {
		scanf("%d%d%d",&n,&m,&p);
		solve(n,m,p);
	}	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值