取石子游戏三大题

取石子游戏三大题

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

取石子游戏1

题目描述

原题来自: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<iostream>

#include<cstdio>

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)||(x<l&&x<r))L[i][j]=x;

                else if(r<x&&x<l)L[i][j]=x-1;

                else L[i][j]=x+1;

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

                if(x==l)R[i][j]=0;

                else if((x>l&&x>r)||(x<l&&x<r))R[i][j]=x;

                else if(r<x&&x<l)R[i][j]=x+1;

                else R[i][j]=x-1;

            }

        puts(a[1]==L[2][n]?"0":"1");

    }

}

取石子游戏 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<stdio.h>

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。

题解:

博弈论

源代码:

#include<stdio.h>
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

发布了50 篇原创文章 · 获赞 51 · 访问量 1387

猜你喜欢

转载自blog.csdn.net/m0_45682806/article/details/104045050
今日推荐