A Puzzle for Pirates
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 141 Accepted Submission(s): 32
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
The situation gets complicated when a few gold pieces were divided among many pirates.
Author
Otter
Source
TJU Contest August 2006
Recommend
linle
题意:有n个海盗,m块金子,n个海盗标记为1~n,标号为n的人先提出一个分金决策,如果有一半或者超过一半的人(包括他自己)支持这个方案,那么就立刻分金,否则就把这个人丢下海,然后轮到下一个人决策。现在问标号为p的人最少得到多少金?
表示要做出这题是需要很严谨的思维的。
具体思路可以参考这 http://blog.csdn.net/acm_cxlove/article/details/7853916#comments,讲的很详细,但是貌似存在一点点小问题,我还是把思路过一遍。
正如这位大神说的,我们决策的优先级当然是先保命,然后才是拿更多的金子,最后才是杀人。(orz)
分析这种问题当然先从简单的开始,只有一个人的情况是显而易见的。自己拿所有的金子。
假如只剩两个人,先决策的那个人支持自己的方案就已经达到一半的人支持自己了,所以他肯定把所有的金子分给自己。
只剩三个人的时候,3号知道如果自己死了,那么2号肯定就把所有的金子都给自己,这样1号一点好处也没有,所以他就拿一个金子去贿赂1号,1号肯定会支持他,所以他得到了剩下的所有金子。
如果只有4个人的时候,4号知道如果自己死了,那么1号拿到1个金子,2号什么都没有,3号拿到剩下的所有金子,所以4号就贿赂2号,给他一个金子,这样自己拿剩下的所有金子。
如果只有5个人的时候,5号知道如果自己死了,那么1号和3号什么什么都拿不到,2号拿到1个金子,4号拿到剩下的所有金子,那么他就贿赂1号和3号……
依次类推下去,我们得到一个规律,就是轮到谁决策的时候,谁就贿赂和自己奇偶性相同的人,然后把剩下的金子给自己。
分析到这里,仿佛问题得到了完美解决,这就是我佩服大神的地方,其实不然,还存在很大问题,就是金子不够贿赂要怎么办?
假设有n 个人,m个金子。
情况一、n<=2m的时候,和自己奇偶性相同的人各拿到一个金子,剩下的金子归自己。
情况二、n=2m+1的时候,n刚好保命,和他奇偶性相同的人各拿到一个金子。
当n>2m+1的时候,情况就比较复杂了。
我们也如大神假设的有500个人,100个金子。
201号人以及他之前的人我们在情况一和二考虑过了。
202号人,除了他自己,他还需要100个人来支持他,金子正好够贿赂这100个人,所以他可以保命。
203号人,他还需要101个人来支持他,显然金子不够用,所以他只能死了。
204号人,他还需要101个人来支持他,他知道自己死了,203号人必死,所以203号人必然会支持他的,所以他只要贿赂100个人,金子够用,他刚好保命。
205号人,他还需要102个人支持他,如果拿100个金子去贿赂之前那100个人,就没多余的金子了,而203,204本来就可以保命,所以肯定没有必要去支持他,所以205必死。
206号人,他还需要102个人来支持他,他要是死了,205必死,所以205会支持他,那么还需要101个人支持他,用100个金子去贿赂之前的100个人,显然204和203还是不会支持他,所以他必死。
207号人,他还需要103个人来支持他,他要是死了,205,206必死,所以他们肯定支持他,但是还是需要贿赂101个人,所以他也只好死了。
208号人,他还需要103个人支持他,他要是死了,205,206,207必死,所以他们必定支持他,所以正好还有100个金子去贿赂先前的那100个人,所以他刚好保命……
由此我们几乎看到规律了,就是标号为2m+2^k的人是刚好保命的。而在2m+2^(k-1)~2m+2^k之间的人是必死的。
到这里问题就得到完美解答了。
情况三、2m+2^k刚好保命
情况四、2m+2^(k-1)~2m+2^k必死。
本来没有完全理解,写到这里的时候完全的理解了这个问题,再次感谢这位大神 http://blog.csdn.net/acm_cxlove/article/details/7853916#comments
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define C 240
#define TIME 10
#define inf 1<<25
#define LL long long
using namespace std;
//保存2的幂
int fac[15]={2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
void slove(int n,int m,int p){
//金币够贿赂的情况
if(n<=2*m){
//不是决策者,而且奇偶性相同,都能被贿赂
if(n!=p&&(n%2==p%2))
printf("1\n");
//剩下的都是决策者拥有
else if(n==p)
printf("%d\n",m-(n-1)/2);
else
//其余人分不到金币,他们的决策不影响全局
printf("0\n");
return ;
}
//这时候的不同在于决策者不能拿金币
else if(n==2*m+1){
if(p<2*m&&p&1)
printf("1\n");
else
printf("0\n");
return ;
}
int t=n-2*m,i;
//这是刚好保命的情况,对于决策者来说,肯定没有金币
//对于其它人来说,要么肯定没有金币,要么可能没有金币,不确定性
for( i=0;i<14;i++){
if(t==fac[i]&&p==t)//这应该加上p==t
{
printf("0\n");
return;
}
}
// int i;
for( i=1;i<14;i++)
if(t<fac[i])
{
//决策者必死
if(p>2*m+fac[i-1]&&p<2*m+fac[i])
printf("Thrown\n");
else
printf("0\n");
return ;
}
}
int main(){
int t,n,m,p;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&p);
slove(n,m,p);
}
return 0;
}