各位勇敢者要玩的第一个游戏是什么呢?很简单,它是这样定义的:
1、 本游戏是一个二人游戏;
2、 有一堆石子一共有n个;
3、 两人轮流进行;
4、 每走一步可以取走1…m个石子;
5、 最先取光石子的一方为胜;
如果游戏的双方使用的都是最优策略,请输出哪个人能赢。
只有一堆n个物品,双方轮流从这堆里取出物品,规定每次至少取1个,最多取m个,先取完者获胜。
1.如果物品n=m+1,如果先手取x个,那么后手每次取m+1-x个,那么后手必赢。
2.如果物品n=a*(m+1),每回合依然,先手取x个,后手每次取m+1-x个,a回合结束后,还是后手必赢。
3.如果物品n=a*(m+1)+b,此时先手先考虑,如果他采取最优策略,他可以先取b个石子,这样他把n=a*(m+1)的局面扔给后手,此刻后手成为了第二种情况的先手,他成为了第二种情况的后手,这个时候的后手必赢。
所以我们发现了,如果n%(m+1)==0,先手必败,否则的话,后手必胜。
#include
#include
using namespace std;
int main()
{
int n,m,t;
cin>>t;
while(t--)
{
cin>>n>>m;
int mm = n%(m+1);
if(mm==0)
{
cout<<"second"<
它就是:两个人轮流报数,每次至少报一个,最多报m个,谁能报到大于等于n的人获胜。
当然本质是一样的
第二题:hdu2188
他决定通过捐款来决定两人谁能入选。
选拔规则如下:
1、最初的捐款箱是空的;
2、两人轮流捐款,每次捐款额必须为正整数,并且每人每次捐款最多不超过m元(1<=m<=10)。
3、最先使得总捐款额达到或者超过n元(0
#include
#include
using namespace std;
int main()
{
int n,m,t;
cin>>t;
while(t--) //目标为n元
{
cin>>n>>m;
if(n%(m+1)==0)
{
cout<<"Rabbit"<
此类题目的通用方法:
P点: 即必败点,某玩家位于此点,只要对方无失误,则必败;
N点: 即必胜点,某玩家位于此点,只要自己无失误,则必胜。
我们可以打表递推找些规律
Recently kiki has nothing to do. While she is bored, an idea appears in his mind, she just playes the checkerboard game.The size of the chesserboard is nm.First of all, a coin is placed in the top right corner(1,m). Each time one people can move the coin into the left, the underneath or the left-underneath blank space.The person who can’t make a move will lose the game. kiki plays it with ZZ.The game always starts with kiki. If both play perfectly, who will win the game?
对于一个nm的地图,两人轮流从地图右上角开始移动硬币,每次只能朝下走,朝左走,或者左下走,最先不能移动的人失败。
很明显,从右上角走到左下角共需要n-1+m-1步,朝左走或者朝右走是走了一步,朝左下的方向走是走了两步。
似乎,这个题可以转换成一模一样的巴士博弈:一共要走(n+m-2)步,每人最少走一步,最多走两步,先走完的人获胜。
但是这样考虑不对,因为如果走到地图的最下边或者最左边,剩下只能朝下走或者朝右走。
所以我们可以通过pn分析问题
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | ||||||
2 | ||||||
3 | ||||||
4 | ||||||
5 | p |
2.再考虑(5 ,2)点,当玩家A位于(5,2)点时,玩家B只能往左走到达必败点(5,1),说明此刻这个点,是必胜点N,同理可以推出(5,3)点,同理可以推出第五行和第一列的所有坐标的状态。
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | p | |||||
2 | n | |||||
3 | p | |||||
4 | n | |||||
5 | p | n | p | n | p | n |
3.然后我们此刻只能去推(4,2)点的状态,因为只有这个点的三个方向的状态是确定的(4,1)(5,1)(5,2),如果玩家A位于(4,2)点,那么玩家B移动硬币的话,肯定要想办法把玩家A引导到一个必败状态,而且他有的选,那就是移动到(5,1)所以(4,2)点就是必胜点。
然后也找出了递推顺序,先左下角,再两边。
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | p | n | p | n | p | n |
2 | n | n | n | n | n | n |
3 | p | n | p | n | p | n |
4 | n | n | n | n | n | n |
5 | p | n | p | n | p | n |
4.规律,当n和m都为奇数时必败,反之必胜
#include
#include
using namespace std;
int main()
{
int n,m;
while(cin>>n>>m)
{
if(n==0 && m==0)
{
break;
}
if(n&1 && m&1)
{
cout<<"What a pity!"<
题目描述:
要种田得有田才行,Lele听说街上正在举行一场别开生面的拍卖会,拍卖的物品正好就是一块20亩的田地。于是,Lele带上他的全部积蓄,冲往拍卖会。
后来发现,整个拍卖会只有Lele和他的死对头Yueyue。
通过打听,Lele知道这场拍卖的规则是这样的:刚开始底价为0,两个人轮流开始加价,不过每次加价的幅度要在1~N之间,当价格大于或等于田地的成本价 M 时,主办方就把这块田地卖给这次叫价的人。
Lele和Yueyue虽然考试不行,但是对拍卖却十分精通,而且他们两个人都十分想得到这块田地。所以他们每次都是选对自己最有利的方式进行加价。
由于Lele字典序比Yueyue靠前,所以每次都是由Lele先开始加价,请问,第一次加价的时候,
Lele要出多少才能保证自己买得到这块地呢?
本题目包含多组测试,请处理到文件结束(EOF)。每组测试占一行。 对于每组数据,在一行里按递增的顺序输出Lele第一次可以加的价。两个数据之间用空格隔开。 n=a*(x+m+1-x)+b
每组测试包含两个整数M和N(含义见题目描述,0
如果Lele在第一次无论如何出价都无法买到这块土地,就输出"none"。思路
当b=0时,必输,输出"none"
如果不能一次买到既a!=0,就要加(m+1)的倍数钱,但是最多加m钱,这就矛盾了,所以如果不能一次买到,就是0;
如果能一次买到,出价区间为[b,m],(哦,这个题面的n和m刚好是反过来的)。#include