博弈-巴什博弈

只有一堆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者勝。
對於巴什博奕,那麼我們規定,如果最後取光者輸,那麼又會如何呢?
(n-1)%(m+1)==0則後手勝利
先手會重新決定策略,所以不是簡單的相反行的
例如n=15,m=3
後手 先手 剩餘
0 2 13
1 3 9
2 2 5
3 1 1
1 0 0
先手勝利 輸的人最後必定只抓走一個,如果>1個,則必定會留一個給對手


取石子(一)

時間限制:3000 ms  |  內存限制:65535 KB
難度:2
描述
一天,TT在寢室閒着無聊,和同寢的人玩起了取石子游戲,而由於條件有限,他/她們是用旺仔小饅頭當作石子。遊戲的規則是這樣的。設有一堆石子,數量爲N(1<=N<=1000000),兩個人輪番取出其中的若干個,每次最多取M個(1<=M<=1000000),最先把石子取完者勝利。我們知道,TT和他/她的室友都十分的聰明,那麼如果是TT先取,他/她會取得遊戲的勝利麼?
輸入
第一行是一個正整數n表示有n組測試數據
輸入有不到1000組數據,每組數據一行,有兩個數N和M,之間用空格分隔。
輸出
對於每組數據,輸出一行。如果先取的TT可以贏得遊戲,則輸出“Win”,否則輸出“Lose”(引號不用輸出)
樣例輸入
2
1000 1
1 100
樣例輸出
Lose
Win


算法:
最多取m個,則如果總數n%(m+1)爲0,則無論先手取了幾個t1,第二個人都取t2,使得t1+t2==m+1即可獲勝
相反 如果n%(m+1)!=0 ,則先手不餘數去掉,之後按上述方案,即可獲勝


 
#include<iostream>
using namespace std;
int main()
{
	int k;
	long m,n;
	cin>>k;
	while(k--)
	{
		cin>>n>>m;
		if(n%(m+1)==0)
			cout<<"Lose"<<endl;
		else
			cout<<"Win"<<endl;
	}
}        


通過打聽,Lele知道這場拍賣的規則是這樣的:剛開始底價爲0,兩個人輪流開始加價,不過每次加價的幅度要在1~N之間,當價格大於或等於田地的成本價 M 時,主辦方就把這塊田地賣給這次叫價的人。
Lele和Yueyue雖然考試不行,但是對拍賣卻十分精通,而且他們兩個人都十分想得到這塊田地。所以他們每次都是選對自己最有利的方式進行加價。
由於Lele字典序比Yueyue靠前,所以每次都是由Lele先開始加價,請問,第一次加價的時候,
Lele要出多少才能保證自己買得到這塊地呢?
Input
本題目包含多組測試,請處理到文件結束(EOF)。每組測試佔一行。
每組測試包含兩個整數M和N(含義見題目描述,0<N,M<1100)
Output
對於每組數據,在一行裏按遞增的順序輸出Lele第一次可以加的價。兩個數據之間用空格隔開。
如果Lele在第一次無論如何出價都無法買到這塊土地,就輸出"none"。
Sample Input
4 2 3 2 3 5
Sample Output
1 none 3 4 5

代碼:


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int main()
{
    int t,n,m,i;
    while(~scanf("%d%d",&n,&m))
    {
        if(n<=m)//n<=m先手必勝
        {
            for(i = n; i<=m; i++)
                if(i==n)
                    printf("%d",i);
                else
                    printf(" %d",i);
            printf("\n");
            continue;
        }
        if(n%(m+1))//必勝態
        {
            int flag = 0;
            for(i = 1; i<=m; i++)
            {
                if((n-i)%(m+1)==0)//必須留下m+1的倍數
                {
                    if(flag == 0)
                        printf("%d",i);
                    else
                        printf(" %d",i);
                    flag++;
                }
            }
            printf("\n");
        }
        else
            printf("none\n");
    }

    return 0;
}






















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章