• 巴什博奕


    巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规
    定每次至少取一个,最多取m个。最后取光者得胜。

        显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:如果n=(m+1)*r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。
        这个游戏还可以有一种变相的玩法:两个人轮流报数,每次至少报一个,最多报十
    个,谁能报到100者胜。

    HDU 1846

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

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

    Sample Input
    2
    23 2
    4 3

    Sample Output
    first
    second

     1 # include <iostream>
     2 # include <cstdio>
     3 using namespace std ;
     4 
     5 int a[110] ;
     6 
     7 int main ()
     8 {
     9     int T ;
    10     scanf("%d" , &T) ;
    11     while (T--)
    12     {
    13         int n , m ;
    14         scanf("%d %d" , &n , &m) ;
    15         if (n % (m+1) == 0)
    16           printf("second
    ") ;
    17         else
    18           printf("first
    ") ;
    19     }
    20     
    21     
    22     
    23 }
    View Code

    HDU 2149 拍卖

    刚开始底价为0,两个人轮流开始加价,不过每次加价的幅度要在1~N之间,当价格大于或等于田地的成本价 M 时,主办方就把这块田地卖给这次叫价的人。第一次加价的时候,
    Lele要出多少才能保证自己买得到这块地呢?

    思路:一堆数量为M的石子,每次只能拿1-N ,当N >= M 先手可以一次拿完

    Sample Input
    4 2 // m n
    3 2
    3 5

    Sample Output
    1
    none
    3 4 5

     1 # include <iostream>
     2 # include <cstdio>
     3 using namespace std ;
     4 
     5 int a[110] ;
     6 
     7 int main ()
     8 {
     9 
    10     int n , m ;
    11     while (scanf ("%d %d" , &m , &n) != EOF )
    12     {
    13         int i ;
    14         if (m > n)
    15         {
    16             if (m % (n + 1) == 0)
    17                printf("none
    ") ;
    18             else
    19                printf("%d
    " , m % (n + 1)) ;
    20         }
    21         else
    22         {
    23             for (i = m ; i < n ; i++)
    24                printf("%d " , i) ;
    25             printf("%d
    " , n) ;
    26         }
    27     }
    28     
    29     
    30 }
    View Code

    HDU 2188 捐款

    选拔规则如下:
    1、最初的捐款箱是空的;
    2、两人轮流捐款,每次捐款额必须为正整数,并且每人每次捐款最多不超过m元(1<=m<=10)。
    3、最先使得总捐款额达到或者超过n元(0<n<10000)的一方为胜者,则其可以亲赴灾区服务。
    我们知道,两人都很想入选志愿者名单,并且都是非常聪明的人,假设林队先捐,请你判断谁能入选最后的名单?

    如果林队能入选,请输出字符串"Grass", 如果徐队能入选,请输出字符串"Rabbit"

    Sample Input
    2
    8 10 // n m
    11 10

    Sample Output
    Grass
    Rabbit

     1 # include <iostream>
     2 # include <cstdio>
     3 using namespace std ;
     4 
     5 int a[110] ;
     6 
     7 int main ()
     8 {
     9 
    10     int T ;
    11     scanf("%d" , &T) ;
    12     while (T--)
    13     {
    14         int n , m ;
    15         scanf("%d %d" , &n , &m) ;
    16         if (n <= m)
    17           printf("Grass
    ") ;
    18         else
    19         {
    20             if (n % (m + 1) == 0)
    21               printf("Rabbit
    ") ;
    22             else
    23               printf("Grass
    ") ;
    24         }
    25     }
    26     
    27     
    28     
    29 }
    View Code

    HDU 2147 走棋盘

    题目的意思是从棋盘的最右上角到左下角,其中只可以走三个方向, 左边, 下边,左下边,不能移动着失败,问先手是否胜利

    Sample Input
    5 3
    5 4
    6 6
    0 0

    Sample Output
    What a pity!
    Wonderful!
    Wonderful!

    //一切博弈都是找规律
    //题目的意思是从棋盘的最右上角到左下角,其中只可以走三个方向, 左边, 下边,左下边,不能移动着失败,问先手是否胜利
    //根据博弈论的理论,先从左下角开始分析
    /*
    * 博弈论:组合博弈
    * 必败点(P点) :前一个选手(Previous player)将取胜的位置称为必败点。
    * 必胜点(N点) :下一个选手(Next player)将取胜的位置称为必胜点。
    * 必败(必胜)点的属性:
    * (1) 所有终结点是必败点(P点);
    * (2) 从任何必胜点(N点)操作,至少有一种方法可以进入必败点(P点);
    * (3)无论如何操作, 从必败点(P点)都只能进入必胜点(N点).
    * 由上面的属性得到该题的算法:
    * 步骤1:将所有终结位置标记为必败点(P点);
    * 步骤2: 将所有一步操作能进入必败点(P点)的位置标记为必胜点(N点)
    * 步骤3:如果从某个点开始的所有一步操作都只能进入必胜点(N点) ,则将该点标记为必败点(P点) ;
    * 步骤4: 如果在步骤3未能找到新的必败(P点),则算法终止;否则,返回到步骤2。
    * 由上面的算法计算一个例子:
    * 我们可以把问题转换成从(1,1)走到(n,m) (方便等下得出结论)
    * 但n=8,m=9的情况
    * NNNNNNNNN
    * PNPNPNPNP
    * NNNNNNNNN
    * PNPNPNPNP
    * NNNNNNNNN
    * PNPNPNPNP
    * NNNNNNNNN
    * PNPNPNPNP
    *初始点(1,1)为N所以输出Wonderful!
    *从这里例子就可以很清楚得看出当n和m都为奇数时,初始点(1,1)才会是P。
    *因此该题只需判断n,m是否同时为奇数即可。
    */

     1 # include <iostream>
     2 # include <cstdio>
     3 using namespace std ;
     4 
     5 int main ()
     6 {
     7 
     8     int n , m ;
     9     while (scanf("%d %d" , &n , &m) )
    10     {
    11         if (n == 0 && m == 0)
    12            break ;
    13         if (n & 1 && m & 1)
    14           printf("What a pity!
    ") ;
    15         else
    16           printf("Wonderful!
    ") ;
    17     } 
    18     
    19     
    20     
    21 }
    View Code

    HUD 2897 变形BASH

    大意:一堆石子共有n个,A,B两人轮流从中取,每次取的石子数必须
    在[p,q]区间内,若剩下的石子数少于p个,当前取者必须全部取完。
    最后取石子的人输。给出n,p,q,问先取者是否有必胜策略?

    Bash博弈的变形
    假设先取者为A,后取者为B,初始状态下有石子n个,除最后一次每次取的石子个数必须在[p,q]区间内,则:
    1.若当前石子共有n = (p+q)*r个,则A必胜,必胜策略为:
    A第一次取q个,以后每次若B取k个,A取(p+q-k)个,如此最后必剩下p个给B,A胜
    2.若n = (p+q)*r+left,(1<left<=p),则B必胜,必胜策略为:
    每次取石子活动中,若A取k个,则B取(p+q-k)个,那么最后必剩下left个给A,
    此时left<=p,A只能一次取完,B胜
    3.若n = (p+q)*r+left,(p<left<p+q),则A必胜,必胜策略为:
    A第一次取t(1<left-t<=p)个,以后每次若B取k个,A取(p+q-k)个,
    那么最后必剩下1<left-t<=p个给B,A胜

    Sample Input
    7 2 4
    6 2 4

    Sample Output
    LOST
    WIN

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cmath>
     4 # include <algorithm>
     5 using namespace std ;
     6 
     7 int main ()
     8 {
     9     int n , p , q ;
    10     while (scanf("%d %d %d" , &n , &p , &q) != EOF)
    11     {
    12         int t ;
    13         t = n % (p + q) ;
    14         
    15         if (t <= p && t > 0)
    16           printf("LOST
    ") ;
    17         else
    18           printf("WIN
    ") ;
    19     }
    20     
    21     return 0 ;
    22 }
    View Code

    HDU 1847 拿牌的时候只能2的幂次(找规律法 也可用SG大法)

    作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的:
    1、 总共n张牌;
    2、 双方轮流抓牌;
    3、 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
    4、 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
    假设Kiki和Cici都是足够聪明(其实不用假设,哪有不聪明的学生~),并且每次都是Kiki先抓牌,请问谁能赢呢?


    Sample Input
    1 //n
    3

    Sample Output
    Kiki
    Cici

    这题如果你是先手,考虑你的必胜态。注意,因为任何正整数都能写成若干个2的整数次方幂之和。由于规定只能取2的某个整数次方幂,只要你留给对手的牌数为3的倍数时,那么你就必赢,因为留下3的倍数时,对手有两种情况:
    1:如果轮到对方抓牌时只剩3张牌,对方要么取1张,要么取2张,剩下的你全取走,win!
    2:如果轮到对方抓牌时还剩3*k张牌,对手不管取多少,剩下的牌数是3*x+1或者3*x+2。轮到你时,你又可以构造一个3的倍数。 所以无论哪种情况,当你留给对手为3*k的时候,你是必胜的。
    题目说Kiki先抓牌,那么当牌数为3的倍数时,Kiki就输了。否则Kiki就能利用先手优势将留给对方的牌数变成3的倍数,就必胜。

     1 # include <iostream>
     2 # include <cstdio>
     3 using namespace std ;
     4 
     5 int main ()
     6 {
     7     
     8     int n ;
     9     while (scanf("%d" , &n ) != EOF)
    10     {
    11         if (n % 3 == 0)
    12           printf("Cici
    ") ;
    13         else
    14           printf("Kiki
    ") ;
    15         
    16     } 
    17     
    18     
    19     
    20 }
    View Code

    HDU 4764 写数字

    题意:
    两个人写数字,要求当前个写的数字Y与前一个写的数字X满足:
    1. 1 <= Y - X <= k
    2. Y要求小于N(第一次取只需满足1<=Y<=k);
    不都满足则输。
    思路:
    可将题目意思理解为取石子(题目有提示),取的石子是有规定的,谁能取到第N-1个,那么就能赢得比赛。
    写的数字>=N就输了 所以总石子数为N-1

    Sample Input
    1 1
    30 3
    10 2
    0 0

    Sample Output
    Jiang
    Tang

    Jiang

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 using namespace std ;
     5 
     6 
     7 
     8 int main ()
     9 {
    10     int n , k ;
    11     while(scanf("%d %d" , &n , &k) )
    12     {
    13         if (n == 0 && k == 0)
    14            break ;
    15         if ((n - 1) % (k + 1) == 0)
    16           printf("Jiang
    ") ;
    17         else
    18           printf("Tang
    ") ;
    19     }
    20     
    21     
    22     return 0 ;
    23 }
    View Code
  • 相关阅读:
    Learning_the_bash_Shell_Third_Edition 15/n
    Learning_the_bash_Shell_Third_Edition 14/n
    Learning_the_bash_Shell_Third_Edition 13/n
    cvb源码分析,resful规范,drf,drf序列化组件,95
    rest_framework登录组件,权限组件
    forms组件
    分页器
    基于ajax提交数据
    回顾django内容
    多表操作
  • 原文地址:https://www.cnblogs.com/mengchunchen/p/4490713.html
Copyright © 2020-2023  润新知