组合游戏简单题


UVA - 11859 - Division Game

题目传送:Division Game

AC代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 10005;

int n, m, t;

int match[55];//把一行的若干个数都变为他们的真因子,即拿掉了一些素因子,即可以看成一堆火柴中取出几根来,所以可以看做Nim类组合游戏

int chu[maxn];
int to[maxn];//计算出每个数字的素因子个数

void init() {//打表计算素因子
    to[1] = 0;
    for(int i = 2; i < maxn; i ++) chu[i] = i;

    for(int i = 2; i < maxn; i ++) {
        if(to[i]) continue;
        to[i] ++;
        for(int j = 2 * i; j < maxn; j += i) {
            while(chu[j] % i == 0) {
                to[j] ++;
                chu[j] /= i;
            }
        }
    }
}

int main() {
    init();
    int T;
    scanf("%d", &T);
    for(int cas = 1; cas <= T; cas ++) {

        memset(match, 0, sizeof(match));

        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m; j ++) {
                scanf("%d", &t);
                match[i] += to[t];
            }
        }

        //因为题目可以看做Nim游戏,所以sg数值即为火柴数值的异或和
        int sg = match[1];
        for(int i = 2; i <= n; i ++) {
            sg = sg ^ match[i];
        }

        if(sg == 0) printf("Case #%d: NO\n", cas);//sg为0时先手必败,反之必胜
        else printf("Case #%d: YES\n", cas);

    }
    return 0;
}

UVALive - 5059 - Playing With Stones

题目传送:Playing With Stones

此题可以先打表来找规律。

打表代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 100;
int SG[maxn];
int vis[maxn];

int main() {
    SG[1] = 0;//只有一个的时候不能拿,为必败状态
    for(int i = 2; i <= 30; i ++) {
        memset(vis, 0, sizeof(vis));
        for(int j = 1; j * 2 <= i; j ++) vis[SG[i-j]] = 1;
        for(int j = 0;; j++) if(!vis[j]) {
            SG[i]  = j;
            break;
        }
        printf("%d ", SG[i]);
    }
    return 0;
}

规律为:

n为偶数时,SG(n) = n / 2;

n为奇数时,SG(n) = SG(n/2);

AC代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

LL SG(LL x) {
    return (x & 1) ? SG(x / 2) : x / 2;
}

int main() {
    int T;
    cin >> T;
    while(T --) {
        int n;
        LL a, ans = 0;
        cin >> n;
        for(int i = 0; i < n; i ++) {
            cin >> a;
            ans ^= SG(a);
        }   

        if(ans) cout << "YES\n";
        else cout << "NO\n";

    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 21:23:25

组合游戏简单题的相关文章

noip复习之数学(4)——组合游戏

我们在此专题中将考虑这样一类组合游戏: (1)两个游戏者轮流操作 (2)游戏的状态集有限,并且不管双方怎么走,都不会再出现以前的状态.这保证了游戏在有限步内结束. (3)谁不能操作谁输,这样的规则避免了平局的出现. 而且我们只考虑公平游戏,即如果一个游戏者可以把状态A变为B,另一个游戏者也可以.国际象棋并不是公平游戏,因为白方可以移动白子,而黑方却不能移动白子. 状态图:为方便描述,我们可以把游戏中的状态画成图.每个节点是一个状态,每条边代表从一个状态转移到另一个状态的操作. 注意:先手必胜状态

组合游戏(博弈)

昨天看大白书翻到了组合游戏这章,看着发觉原来是博弈论的内容,于是便看下去了.真是不看不知道,一看才知道自己的水平有多弱,不过好在还是集中精神地看了大部分.从Nim游戏(n堆石子,每人每次可以从任意一堆中取至少1个.至多整堆的石子,不能取者为输)开始讲起,引入必胜态.必败态的概念—— 1. 一个状态是必败状态当且仅当它的所有后继都是必胜状态. 2. 一个状态是必胜状态当且仅当它至少有一个后继是必败状态. 这是刘汝佳大神说的,说得通俗一点就是,必败态的所有后继都是必胜态,必胜态只需有一个后继是必败态

[原博客] 组合游戏学习

阅读了<由感性认识到理性认识——透析一类搏弈游戏的解答过程>.<解析一类组合游戏>.<组合游戏略述——浅谈SG游戏的若干拓展及变形>这三篇论文,对组合游戏以及SG函数有了更深的理解.这篇文章摘下了这三篇论文的部分重要内容,以及部分我对组合游戏的理解. 一些名词与约定: 游戏:这里的游戏指的并不是平时玩的那些游戏(Dota2啥的),而是只一些如Nim取石子之类的“益智”组合游戏.并且,我们关注的不是游戏好不好玩,而是游戏有没有必胜策略.下文详细介绍. 状态:用一些数字来表

POJ 2348 Euclid&#39;s Game 组合游戏

题目大意:有两个人玩游戏,有两堆石子,每次一个人要从其中一堆石子中拿走一些石子,当出现有一对石子变成0的时候这个人就输了,另一个人就赢了.给出初始石子有多少,问谁能赢. 思路:基础的组合游戏的判定问题,这个题没有给数据范围,非常的坑爹,据说需要long long. 第一次做组合游戏的题目,想想还有些小激动呢.昨天听同学讲了讲,我来现学现卖一下: 由于组合游戏的公平性,那么:如果一个状态的子状态会使先手必败,那么当前状态的先手必胜: 如果不存在一个子状态会使先手必败,那么当前状态先手必败. 利用这

组合游戏 - SG函数和SG定理

在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的性质: 1.所有终结点是 必败点 P .(我们以此为基本前提进行推理,换句话说,我们以此为假设) 2.从任何必胜点N 操作,至少有一种方式可以进入必败点 P. 3.无论如何操作,必败点P 都只能进入 必胜点 N. 我们研究必胜点和必败点的目的时间为题进行简化,有助于

POJ 2068 Nim 组合游戏

题目大意:有一堆石子,两伙人,围在一起坐,坐的顺序是ABABABAB....每一个人最多能取a[i]个石子,取走最后一个石子的就输了.问谁能赢. 思路:朴素的组合游戏判定问题,这个题给了数据范围,可以进行记忆化搜索.f[i][j]为还剩下i个石子,到了第j个人的时候的状态,然后记忆化一下. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #

组合游戏学习笔记 [补档]

基础 满足以下条件的游戏是组合游戏: 有两人参与游戏, 轮流作出决策 无法作出决策的人失败, 然后游戏结束 游戏总能在有限次决策后结束 游戏的同一个状态不会多次到达 任意一个参与者在某一确定状态下可以作出的决策集合只与当前状态有关 定义先手必败状态为必败态, 先手必胜状态为必胜态, 则我们有 无法进行任何移动的状态是必败态. 可以移动到必败态的状态的是必胜态. 所有移动都只能得到必胜态的状态是必败态. 考虑如何判断一个游戏中, 先手是否必胜: 根据定义, 由于游戏中任意状态都不可能重复出现, 因

组合游戏与博弈

[引言] 分金币问题:有100个金币,两个人轮流从这堆金币中取金币,规定每次至少取1个,最多取5个.取完最后一枚金币的人获胜.假入你先手取金币,对方是足够聪明的,你能找到一种必胜的方法吗? [问题分析] 首先我们考虑到这样一个简单的事实,如果最后把6个金币留给对方去取,那么很显然,对方必败.再往前推进一步,如果把12枚金币留给对方去取,对方也必败. 为什么呢?原因很简单,不论对方取几个,我都能够把金币取成6个,这样就回到上一个对方必败的局势了. 那么我们可以更进一步地推出,如果把金币取成18个,

博弈论题目总结(一)——组合游戏

人类的本质是什么呢?复读机?鸽子? 博弈问题是很有意思的一类题目 我讲的可能不是很明白,但题目都不难建议自己思考 组合游戏的特点: 1.两个人博弈,轮流做出最优决策 2.玩家在每个时刻做出的决策都是能预测到的,是一个确定的集合 3.每种状态可能有多种方式到达,但同一种状态不能在一次游戏中重复到达,且没有平局的情况 4.只要能进行决策,就一定要决策,不能跳过这个回合 SG组合游戏 我们把每种状态抽象成一个点,在起点有一颗棋子,两个人选取最优策略轮流对这颗棋子进行移动,最后不能移动棋子的人失败 显然