取石子游戏三大题

取石子游戏三大题

———————————————————————————————————————————————————————

取石子游戏

题目描述

原题来自:ZJOI 2009

 

在研究过 Nim 游戏及各种变种之后,Orez 又发现了一种全新的取石子游戏,这个游戏是这样的:

有 n 堆石子,将这 n 堆石子摆成一排。游戏由两个人进行,两人轮流操作,每次操作者都可以从
最左或最右的一堆中取出若干颗石子,可以将那一堆全部取掉,但不能不取,不能操作的人就输了。

Orez 问:对于任意给出一个初始一个局面,是否存在先手必胜策略。

 

输入

第一行为一个整数 T,表示有 T 组测试数据。

对于每组测试数据,第一行为一个整数 n,表示有 n 堆石子,第二行为 n 个整数 a_i,
依次表示每堆石子的数目。

 

输出

对于每组测试数据仅输出一个整数 0 或 1。其中 1 表示有先手必胜策略,0 表示没有。

样例输入

1
4
3 1 9 4

 

样例输出

0

 

题解

数据范围与提示

对于 30% 的数据,10^5n≤5,ai≤105;
对于全部数据,10001≤T≤10,1≤n≤1000,每堆石子的个数小于等于 10^9。 

源代码:

#include

#include

using namespace std;

#define MAX 1010

inline int read()

{

    int x=0;bool t=false;char ch=getchar();

    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();

    if(ch=='-')t=true,ch=getchar();

    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();

    return t?-x:x;

}

int n,a[MAX],L[MAX][MAX],R[MAX][MAX];

int main()

{

    int T=read();

    while(T--)

    {

        n=read();

        for(int i=1;i<=n;++i)a[i]=read();

        for(int i=1;i<=n;++i)L[i][i]=R[i][i]=a[i];

        for(int len=2;len<=n;++len)

            for(int i=1,j=i+len-1;j<=n;++i,++j)

            {

                int x=a[j],l=L[i][j-1],r=R[i][j-1];

                if(x==r)L[i][j]=0;

                else if((x>l&&x>r)||(xl&&x>r)||(x

取石子游戏 1

题目描述

有一种有趣的游戏,玩法如下:

玩家:2 人;

道具:N 颗石子;

规则:

游戏双方轮流取石子;
每人每次取走若干颗石子(最少取 1 颗,最多取 K 颗);
石子取光,则游戏结束;
最后取石子的一方为胜。
假如参与游戏的玩家都非常聪明,问最后谁会获胜?

 

输入

输入仅一行,两个整数 N 和 K 。

输出

输出仅一行,一个整数,若先手获胜输出 1,后手获胜输出 2。

 

样例输入

23 3

 

样例输出

1

 

提示

数据范围与提示对于全部数据,1≤N≤105,1≤K≤N。

题解

博弈论,把k+1,然后用N除以k取余,如果不为0,则输出“1”(不加引号),否则,输出“2”(不加引号)

源代码:

#include

int main() {

    int n,k=k+1;

    scanf("%d%d",&n,&k);

    k=k+1;

    if(n%k!=0) {

        printf("1\n");

    } else {

        printf("2\n");

    }

    return 0;

}

取石子游戏 2

题目描述

有一种有趣的游戏,玩法如下:

玩家:2 人;

道具:N 堆石子,每堆石子的数量分别为 X1,X2,...,Xn;

规则:

游戏双方轮流取石子;
每人每次选一堆石子,并从中取走若干颗石子(至少取 1 颗);
所有石子被取完,则游戏结束;
如果轮到某人取时已没有石子可取,那此人算负。
假如两个游戏玩家都非常聪明,问谁胜谁负?

 

输入

第一行,一个整数 N;

第二行,N 个空格间隔的整数 Xi,表示每一堆石子的颗数。

输出

输出仅一行,一个整数,若先手获胜输出 win,后手获胜输出 lose。

样例输入

4
7 12 9 15

 

样例输出

 
win

 

提示

数据范围与提示

对于全部数据,N≤5×104,1≤Xi≤105。

题解:

博弈论

可以这样想,如果a1 xor a2 xor a3 xor...xor an为0那么后手胜,否则先手胜。
//xor,异或标识(如果不知道异或是什么,可以查看异或(exclusive OR)) 
这个可以用二进制的对称性来辅助思考。

源代码:

#include
int main() {
    int n,x=0,y,i;
    scanf("%d",&n);
    for(i=1; i<=n; ++i) {
        scanf("%d",&y),x^=y;
    }
    if(x) {
        printf("win\n");
    } else {
        printf("lose\n");
    }
    return 0;
}

AC

你可能感兴趣的:(取石子游戏三大题)