HDU博弈

第一个数决定走势,第二个数只能控制范围


HDU 1846 加法

Problem Description
十年前读大学的时候,中国每年都要从国外引进一些电影大片,其中有一部电影就叫《勇敢者的游戏》(英文名称:Zathura),一直到现在,我依然对于电影中的部分电脑特技印象深刻。
今天,大家选择上机考试,就是一种勇敢(brave)的选择;这个短学期,我们讲的是博弈(game)专题;所以,大家现在玩的也是“勇敢者的游戏”,这也是我命名这个题目的原因。
当然,除了“勇敢”,我还希望看到“诚信”,无论考试成绩如何,希望看到的都是一个真实的结果,我也相信大家一定能做到的~

各位勇敢者要玩的第一个游戏是什么呢?很简单,它是这样定义的:
1、  本游戏是一个二人游戏;
2、  有一堆石子一共有n个;
3、  两人轮流进行;
4、  每走一步可以取走1…m个石子;
5、  最先取光石子的一方为胜;

如果游戏的双方使用的都是最优策略,请输出哪个人能赢。
 

Input
输入数据首先包含一个正整数C(C<=100),表示有C组测试数据。
每组测试数据占一行,包含两个整数n和m(1<=n,m<=1000),n和m的含义见题目描述。
 

Output
如果先走的人能赢,请输出“first”,否则请输出“second”,每个实例的输出占一行。
 

Sample Input
  
  
2 23 2 4 3
 

Sample Output
  
  
first second
尽可能使自己赢,保证最后剩余m个以内时在自己手里,也就是说保证取完倒数第二次的时候最少剩余m + 1个在对方手,first先取也就占了先机,只要first取完以后变成m + 1 的倍数,就肯定会赢(因为second只能取小于等于m个的,等second取完x个之后,first就取m + 1 - x个,剩余的还是m + 1的倍数,也就是说second无论怎么取,first都可以取相对应的个数保证自己的胜利,那么first胜利的前提就是m取完之后是m + 1的倍数,倘若最开始就是m + 1的倍数,first取完之后就不能是m + 1的倍数,而second就能保证取完之后变成m + 1的倍数,second也就能保证自己的胜利)
#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
    int c;
    cin >> c;
    while(c--)
    {
        int n,m;
        scanf("%d%d", &n, &m);
        if(n % (m + 1) == 0)
        {
            printf("second\n");
        }
        else
        {
            printf("first\n");
        }
    }
    return 0;
}



HDU1517 乘法

A Multiplication Game

http://acm.hdu.edu.cn/showproblem.php?pid=1517


Problem Description
Stan and Ollie play the game of multiplication by multiplying an integer p by one of the numbers 2 to 9. Stan always starts with p = 1, does his multiplication, then Ollie multiplies the number, then Stan and so on. Before a game starts, they draw an integer 1 < n < 4294967295 and the winner is who first reaches p >= n.
 

Input
Each line of input contains one integer number n.
 

Output
For each line of input output one line either

Stan wins.

or

Ollie wins.

assuming that both of them play perfectly.
 

Sample Input
  
  
162 17 34012226
 

Sample Output
  
  
Stan wins. Ollie wins. Stan wins.

上面一题m + 1 为可控范围,而在这道题中,2  * 9 = 18 倍为可控范围,假如stan先乘以9,在olline的可控范围内,则乘2,stan继续乘9,olline则乘2,依次循环,当stan不乘9,乘以一个小于9的数来获取胜利,olline会乘一个大于2的数保持在范围内,这样一直到最后,假入stan乘9获胜,那么显然stan获胜,如果最后变成了乘以2才能赢,也就是前一个无论乘多少都到不了n,且此时的乘值再乘一个数就会大于n,第一个乘数决定走势,第二个乘数只能控制范围


#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
    long long n;
    while(~scanf("%lld", &n))
    {
        long long i = 1;
        int k = 1, mul[2] = {2, 9};
        while(i < n)
        {
            i = i * mul[k];
            k = (k + 1) % 2;
        }
        if(k == 0)
            printf("Stan wins.\n");
        else
            printf("Ollie wins.\n");
    }
    return 0;
}

hdu1847 幂

Good Luck in CET-4 Everybody!

Problem Description
大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此。当然,作为在考场浸润了十几载的当代大学生,Kiki和Cici更懂得考前的放松,所谓“张弛有道”就是这个意思。这不,Kiki和Cici在每天晚上休息之前都要玩一会儿扑克牌以放松神经。
“升级”?“双扣”?“红五”?还是“斗地主”?
当然都不是!那多俗啊~
作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的:
1、  总共n张牌;
2、  双方轮流抓牌;
3、  每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
4、  抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
假设Kiki和Cici都是足够聪明(其实不用假设,哪有不聪明的学生~),并且每次都是Kiki先抓牌,请问谁能赢呢?
当然,打牌无论谁赢都问题不大,重要的是马上到来的CET-4能有好的状态。
Good luck in CET-4 everybody!
 
Input
输入数据包含多个测试用例,每个测试用例占一行,包含一个整数n(1<=n<=1000)。
 
Output
如果Kiki能赢的话,请输出“Kiki”,否则请输出“Cici”,每个实例的输出占一行。
 
Sample Input
   
   
1 3
 
Sample Output
   
   
Kiki Cici

第二个是控制范围的,也就是说假如first无论怎样选值second都会赢的,那么这个使second赢的数值加上2的幂次,first就会获胜。

一开始a[0]代表second获胜,a[1]a[2]显然first获胜;

然后判断a[i - 2的幂次]是否等于2,如果等于,说明 i 值first获胜

因为first会决定走势,所以我们判断first的取胜情况

#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
    int a[1010];
    a[0] = 2;
    a[1] = 1;
    a[2] = 1;
    int pow;
    for(int i = 3; i <= 1000; i++)
    {
        pow = 1;
        while(pow <= i)
        {
            //数值为i - pow时second获胜
            //first第一次取,取走pow个,那么second面对的就是i - pow个,是一定会输的数值
            //那么为i时first获胜
            if(a[i - pow] == 2)
            {
                //已经确定了first会赢
                //不用再继续减小了
                a[i] = 1;
                break;
            }
            a[i] = 2;
            pow = pow * 2;
        }
    }
    int b;
    while(~scanf("%d", &b))
    {
        if(a[b] == 1) printf("Kiki\n");
        else printf("Cici\n");
    }
    return 0;
}


HDU2147

kiki's game

Problem Description
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 n*m.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?
 

Input
Input contains multiple test cases. Each line contains two integer n, m (0<n,m<=2000). The input is terminated when n=0 and m=0.

 

Output
If kiki wins the game printf "Wonderful!", else "What a pity!".
 

Sample Input
  
  
5 3 5 4 6 6 0 0
 

Sample Output
  
  
What a pity! Wonderful! Wonderful!

a[1][1]是second,加一行或者加一列或者加一行一列的情况下都是first获胜


按照上面的方法,写出前面的取胜情况表,发现在奇数行奇数列的是second获胜

#include <iostream>
#include <cstdio>
#define maxn 2010
int a[maxn][maxn];
using namespace std;

int main()
{
    int h, l;
    while(~scanf("%d%d", &h, &l))
    {
        if(h == 0 && l == 0)
            break;
        if((h % 2 == 1) && (l % 2 == 1))
            printf("What a pity!\n");
        else
            printf("Wonderful!\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值