codeforce690A2 Collective Mindsets (medium) (from :Helvetic Coding Contest 2016 online mirror )


诶,不知道最近自己是怎么了,英文题的题意总是很迷
题意:“海盗分金”问题,n个人分m个金币(金币是最小单位,不可再分割),首先第一个人提出分配方案,当半数,或半数以上的人同意时,分配完成,不然,杀死第一个人,让第二个人进行提出分配方案,直到人全死光(当然根据题意这是不可能的……)或者一个半数或半数以上的分配方案被提出。每个参与者都是所谓的“非常聪明”的,以及他们的行为遵循以下两个原则:
  1. 自己要确保自己不可以死(当然有时候你不得不死23333)
  2. 满足第一个条件的情况下,获得更多的金币
现在你是第一个人,问你当参与者为n的时候,你至少需要多少金币可以保证自己不被杀死(你可以不给自己金币,并且支持自己的方案,以尽力保证自己不会被杀)。

思路:不妨先思考一下:(为了方便讨论,把最后一个人提出方案的人称为第1个人,第一个提出方案的人称为第n个人)
如果只有1个人,0个金币(只有自己一个人当然不用金币啦)。
如果只有2个人,0个金币(自己不要金币,自己支持自己的方案)。
如果只有3个人,1个金币(如果没有金币,考虑前文两个人的情况,第3个人不能给出比前文两个人更好的分配方案,第3个人只有死,那么第3个人需要一个金币来博取后两个人中一个人的支持)
如果只有4个人,0个金币!!!(没有金币,前文第3个人必死,只能支持第4个人,第4个人支持自己,ok)
5个人,2金币
6个人,1金币
7个人,3金币
8个人,0金币
9个人,4金币
10个人,1金币
…………
有了这种思路就好办了,这时候你会发现题目给了一个提示,样例三,99个人49个金币,很容易想到当n为奇数时,答案为(n-1)/2。(啥?你问我怎么想到的?瞎猜啊……)如果前面一些答案自己推过,你会发现奇数总是处在一个很尴尬的地位,当他没有(n-1)/2个金币时,前面总有人可以提出满足这些金币的分配方案,那么作为第一个提出分配的人,无法提出更好的要求,只有死路一条。除非有(n-1)/2个金币,你可以把这些金币分配给在下一个提出偶数方案的人所提方案中没有得到金币的(n-1)/2个人,加上自己支持自己,你就可以活下来。

那么偶数个人的情况呢?再瞎猜一下(这什么题解啊喂,全是靠猜的= =):当人数为n的幂次时,0个金币就能活下来。这个的证明方法……数学归纳法吗?总之思路是因为n为2的幂次,[n/2+1,n-1]这些人由于拿不出更好的分配方案,会被[1,n/2]这些人投反对票,为了保命,[n/2+1,n-1]这(n/2-1)个人只能支持第n个人,加上第n个人自己支持自己,就ok了。

2的幂次被解决了,那么不是2的幂次的偶数呢?假如说你现在有10个人,1枚金币,由于第6个人有1个金币的分配方案,[7,9]这三个人无法提出更好的分配方案,只能支持第10个,第10个自己支持自己,恰好还有一枚金币收买一个人,ok。这样同理,第18个人也需要1个金币,[11,17]为了保命,是一定会支持第18个人的。也就是说,设m为最接近n且小于等于n的2的幂次,一个偶数需要的金币数是(n-m)/2。
以上。

或者用题解的话说:
• For 0 brains, the survivors are: 1, 2, 4, 8, ...
• For 1 brain, the survivors are: 1, 2, 3, 4, 6, 10 = {1, 2} ∪ (2 + {1, 2, 4, 8, ...})
• For 2 brains, the survivors are: 1, 2, 3, 4, 5, 6, 8, 12 = {1, 2, 3, 4} ∪ (4 + {1, 2, 4, 8, ...})
• For B brains, the survivors are: {1, 2, .., 2 × B} ∪ (2 × B + {1, 2, 4, 8, ...})
Notice that the right-hand side component of the union contains only even numbers! Hence if N is odd, it takes b(N − 1) /2c brains for N to appear in the left-hand side component of the union!

Also note that the right-hand side member of the union holds all numbers which are twice the number of brains plus any power of two. Or stated the other way round, for zombie N, even, to survive, the number of brains needed is N minus any power of 2, divided by two. Since we ask for the smallest such number, you want to subtract the largest power of two smaller than N.

代码:

#include<cstdio>
int main(){
	int n;
	scanf("%d",&n);
	if(n&1) printf("%d\n",(n-1)/2);
	else{
		int m=2;
		while(m<=n) m<<=1;
		m/=2;
		printf("%d\n",(n-m)/2);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值