最简单的巴什博弈
巴什博弈
所谓巴什博弈,是ACM题中最简单的组合游戏,大致上是这样的:
只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取1个,最多取m个,最后取光者得胜。
分析:
显然,如果n = m + 1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:
如果 n = (m + 1) * r + s ,(r为任意自然数,s≤m),即n%(m+1) != 0,则先取者肯定获胜。
每一局,你都必须构建一个局势,这个局势就是每次都留给对手m+1的倍数个物品。因为,如果n=(m+1)r + s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。
//下面就来看一下这类题
好运!该死的英语四级!
Problem Description
大学英语四级考试就要来临了, Kiki和Cici 在紧张的复习之余喜欢打牌放松。“升级”?“斗地主”?那多俗啊!作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的:
1、 总共n张牌;
2、 双方轮流抓牌;
3、 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
4、 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
假设Kiki和Cici都是足够聪明并且每次都是Kiki先抓牌,请问谁能赢呢?
Input
输入数据包含多个测试用例,每个测试用例占一行,包含一个整数n(1<=n<=1000)。
Output
若Kiki能赢的话输出“Kiki”,否则输出“Cici”,每个实例的输出占一行。
Sample Input
1
3
Sample Output
Kiki
Cici
分析:
如果你是先手,考虑你的必胜态。注意,因为任何正整数都能写成若干个2的整数次方幂之和(相当于十进制转二进制)。由于规定只能取2的某个整数次方幂,只要你留给对手的牌数为3的倍数时,那么你就必赢,因为留下3的倍数时,对手有两种情况:
1:如果轮到对方抓牌时只剩3张牌,对方要么取1张,要么取2张,剩下的你全取走,必赢!
2:如果轮到对方抓牌时还剩3*k张牌,对手不管取多少,剩下的牌数是3*x+1或者3*x+2。轮到你时,你又可以构造一个3的倍数。 所以无论哪种情况,当你留给对手为3*k的时候,你是必胜的。
题目说Kiki先抓牌,那么当牌数为3的倍数时,Kiki就输了。否则Kiki就能利用先手优势将留给对方的牌数变成3的倍数,就必胜。
代码如下:
#include <iostream> using namespace std; int main () { int num; while (cin>>num ) { if(num%3!=0) cout<<"Kiki"<<endl; else cout<<"Cici"<<endl; } return 0; }
土地拍卖
Problem Description
小鸡同学和鹏程同学始终没有逃过退学的命运,因为他们没有在程序设计竞赛中获奖,还为了争抢莎莎大打出手。现在等待他们的只能回家种田。要种田得有田才行,小鸡听说街上正在举行一场拍卖会,拍卖的物品正好就是一块田地。于是,小鸡带上他的全部积蓄,冲往拍卖会。后来发现,整个拍卖会只有小鸡和他的死对头鹏程。通过打听,小鸡知道这场拍卖的规则是这样的:刚开始底价为0,两个人轮流开始加价,不过每次加价的幅度要在1~N之间,当价格大于或等于田地的成本价M时,就把这块田地卖给这次叫价的人。小鸡和鹏程虽然比赛不行,但是对拍卖却十分精通,而且他们两个人都十分想得到这块田地。所以他们每次都是选对自己最有利的方式进行加价。由于抽签决定,所以每次都是由小鸡先开始加价,请问,第一次加价的时候,小鸡要出多少才能保证自己买得到这块地呢?
Input
本题目包含多组测试,请处理到文件结束(EOF)。每组测试占一行。每组测试包含两个整数M和N(含义见题目描述,0<N,M<1100)
Output
对于每组数据,在一行里按递增的顺序输出小鸡第一次可以加的价。两个数据之间用空格隔开。如果小鸡在第一次无论如何出价都无法买到这块土地,就输出"none"。
Sample Input
4 2
3 2
3 5
Sample Output
1
None
3 4 5
分析:
这道题就是一般的巴什博弈,如果m%(n+1)=0,就是必败态;如果m<=n,就可能出现多种选择;如果是一般情况就只有上述所说的一种选择
代码如下:
# include<stdio.h> int main() { int n,m; while(scanf("%d %d",&m,&n)!=EOF) { if(m%(n+1)==0) { printf("none\n"); continue; } if(m<=n) { printf("%d",m); for(int i=m+1; i<=n; i++) printf(" %d",i); printf("\n"); continue; } printf("%d\n",m%(n+1)); } return 0; }
浙公网安备 33010602011771号