我是靠谱客的博主 跳跃蜗牛,最近开发中收集的这篇文章主要介绍AtCoder 137 C Distinct Numbers(博弈论),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

AtCoder 137 C Distinct Numbers

题意

给定一个长度为 n ( 2 ≤ n ≤ 3 × 1 0 5 ) nleft(2le nleq3times 10^{5}right) n(2n3×105)的严格递增的自然数序列 A 1 , A 2 , ⋯   , A n A_1,A_2,cdots,A_n A1,A2,,An

  • 现在有两个人在轮流进行如下操作:
    • 选择序列中最大数 m x mx mx,使其变成一个小于 m x mx mx的自然数,并且变化后需要满足:序列中没有相同的数。
    • 然后将由另一个人来对这个序列进行操作。
    • 直至一个人无法操作的时候,则其被判负

思路

做这类博弈题的时候,我一般把自己带入,当作是自己是先手的那个人

  • 首先,做博弈题的第一步就是搞清楚:当你面对什么局面的时候,代表被判负了
    • 被判负,即比最大数 m x mx mx小的所有的自然数都存在了,故这是一个连续的、字典序最小的序列
      • 此处序列的字典序指的是一个数代表一个字符
    • 且因为前面的操作都是合法的,所以它们都是不同的
    • 故被判负的终态为 0 , 1 , 2 , ⋯   , n − 1 0,1,2,cdots,n-1 0,1,2,,n1
  • 考虑什么情况会到达终态(被判负),即被判负倒推一步
    • 我们用移动石子、石字占领位置的模型,来替换掉一个数变成某个数的思想
    • 我们用all表示 0 0 0 n − 1 n-1 n1的所有位置
      • 局面1:假设all中有 1 1 1个空位,且位置 n n n已经被占领了。那么我们直接将其移动到all那个空位,对手面对终态,即表示我们:判胜
      • 局面2:假设all中有 2 2 2个空位,且位置 n n n和位置 n + 1 n+1 n+1已经被占领了。那么我们第一步只能被迫将 n + 1 n+1 n+1移动到一个空位,然后对手面对上面的局面1,即表示对手胜利,也就表示我们的结果为:判负
      • 局面3:假设all中有 3 3 3个空位,且位置 n n n和位置 n + 1 n+1 n+1、位置 n + 2 n+2 n+2已经被占领了。那么我们第一步只能被迫将 n + 2 n+2 n+2移动到一个空位,然后对手面对局面2,即表示对手失败,也就表示我们的结果为:判胜
      • 以此类推,此类all中存在空位,剩余的石子从位置 n n n开始的连续的情况

然后我们开始就讲正解思路,分类讨论以下两种类型

类型一

A [ n ] > A [ n − 1 ] + 1 A[n]>A[n-1]+1 A[n]>A[n1]+1,我们分以下两种情况考虑

  • 如果存在一个方案,让 A [ n ] A[n] A[n]变为某一个比 A [ n − 1 ] A[n-1] A[n1]小的数,使其的后继状态全是必败态( N N N态),那么我们就转移到这个状态,对手必败,等价我们必胜
  • 如果不存在上述这样的一个方案,说明面对上述方案转移到的局面是一个必胜态,那么我们也要想办法让自己面对这样一个必胜态,我们就让对手强制把我们送到这个必胜态,我们让 A [ n ] A[n] A[n]变为 A [ n − 1 ] + 1 A[n-1]+1 A[n1]+1即可。这样对手就会被迫执行上述方案的操作,我们依旧必胜
  • 故综上,当 A [ n ] > A [ n − 1 ] + 1 A[n]>A[n-1]+1 A[n]>A[n1]+1时,是先手必胜的
类型二

A [ n ] = A [ n − 1 ] + 1 A[n]=A[n-1]+1 A[n]=A[n1]+1

此处我先说结论,后证明

  • A [ n ] − ( n − 1 ) A[n]-(n-1) A[n](n1)为奇数时,必胜
  • A [ n ] − ( n − 1 ) A[n]-(n-1) A[n](n1)为偶数时,必败

以下简称 A [ n ] − ( n − 1 ) A[n]-(n-1) A[n](n1)距离

我先举一个局面,大家体会一下, n = 6 n=6 n=6,初始局面 0 , 2 , 3 , 5 , 99 , 100 0,2,3,5,99,100 0,2,3,5,99,100,按照我最上面说的all中有两个空位置,需要考虑的只有99 100,根据上述的结论,距离为100 - 5 = 95是奇数,为必胜态

下面我称我们为A,对手为B

A面对的初始局面为99 100操作后为98 99

B此时面对的局面为98 99,距离为99 - 5 = 94是偶数,结论中为必败态,假设B有两种操作

  • 操作后为45 98,我们操作后为 44 45
  • 操作后为46 98,我们操作后为46 47

我们无论如何始终都可以让B面对最大的数是奇数的局面(必败态,因为例子中n-1为奇数),直到最后一个最大的奇数5

但是怎么为什么这结论就是正确的呢?

博弈论有以下基本性质

  • 必败态的所有后继状态都是必胜态
  • 必胜态的后继状态中至少有一个是必败态

回到我们刚刚说的all的那几种局面,局面1中距离为奇数(必胜),局面2中距离为偶数(必败),局面3中距离为奇数(必胜)

我们可以从局面2中拓展,假设最后两个石子的状态不为n n+1

  • 若为n+1 n+2,则我们移动到n n+1,对手必败,我们必胜
  • 若为n+2 n+3,若我们移动到n+1 n+2,面对这个局面的对手必胜,我们必败;若我们移动到n n+2,对手可以移动到n n+1我们必败;若我们将n+2移动到all中的一个空位置,对手只需再移动一步,我们就面对终态。故面对该状态时我们必败
  • 于是我们便可以数学归纳法,all只有两个空位的时候且最后两个石子连续的情况,距离为奇数必胜,为偶数必败

此时我们还有一个问题没解决,如果all中不止两个空位且最后两个石子连续的情况——即一般情况(因为一个空位的情况我们已经讨论完毕了,即必胜)

结合从局面2的拓展和上述枚举的局面99 100中过程的思想,我们便可证明结论的正确性,相信此时大家已经懂得差不多了,此处我就不在赘述了

代码

最后附上本菜狗的代码

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
int main()
{
    int n, x, y;
    cin >> n;
    rep(i, 3, n)
        cin >> x;
    cin >> x >> y;
    bool win = (y > x + 1) | ((y - (n - 1)) & 1);
    cout << (win ? "Alice" : "Bob") << 'n';
}

最后

以上就是跳跃蜗牛为你收集整理的AtCoder 137 C Distinct Numbers(博弈论)的全部内容,希望文章能够帮你解决AtCoder 137 C Distinct Numbers(博弈论)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(81)

评论列表共有 0 条评论

立即
投稿
返回
顶部