CF 666 (Div. 2) D. Stoned Game博弈论

Posted lasomisolaso~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 666 (Div. 2) D. Stoned Game博弈论相关的知识,希望对你有一定的参考价值。

题意:

n n n堆石头,两个人轮流拿石头。每个人只能从一堆石头中拿走一个,并且这堆石头不能是上一轮另外一个玩家拿过的。谁没有石头拿就输了。

思路:

设当前所有石头堆的石头数量的总和为 S S S

第一种情况:如果某一堆石头的个数大于 ⌊ S 2 ⌋ \\lfloor \\fracS2 \\rfloor 2S ,那么肯定是先手获胜,就是面临这种情况的玩家必胜。

如果一堆石头大于 ⌊ S 2 ⌋ \\lfloor \\fracS2 \\rfloor 2S ,那么其它所有石头的和都比这堆石头少。那么先手只要一直拿这堆石头,后手只能拿其它的石头。一定是后手先将其它的石头消耗完。

第二种情况:如果所有的堆的石头个数都小于等于 ⌊ S 2 ⌋ \\lfloor \\fracS2 \\rfloor 2S ,并且石头的个数是偶数,那这种情况一定是后手胜。也就是说面临这种情况的玩家将必然输。

证明:先手从 n n n堆石头中取出1个石头,石头数量变成 S − 1 S-1 S1 。 后手检查所有的石头,看是否有石头堆的石头个数大于 ⌊ S − 1 2 ⌋ \\lfloor \\fracS-12 \\rfloor 2S1, 有的话直接转第一种情况 ,后手获胜;否则后手就可以随便的拿一个石头。这样石头总数变为 S − 2 S-2 S2 , 还是所有的石头堆的石头数量都小于 ⌊ S − 2 2 ⌋ \\lfloor \\fracS-22 \\rfloor 2S2 。这是因为 ⌊ S − 1 2 ⌋ \\lfloor \\fracS-12 \\rfloor 2S1 = ⌊ S − 2 2 ⌋ \\lfloor \\fracS-22 \\rfloor 2S2 ,因为 S S S是偶数,后手没拿之前就已经没有大于 ⌊ S − 1 2 ⌋ \\lfloor \\fracS-12 \\rfloor 2S1 的,拿了之后更不可能。

还有,因为没有一堆石头的石头个数是大于 ⌊ S 2 ⌋ \\lfloor \\fracS2 \\rfloor 2S, 所以先手拿了之后后手必然是可以继续拿的。

所以这种情况就是,先手拿之后,后手不是转成必胜,就可以继续拿。所以后手必胜。

第三种情况:如果所有的堆的石头个数都小于等于 ⌊ S 2 ⌋ \\lfloor \\fracS2 \\rfloor 2S ,并且石头的个数是奇数。这种情况先手必胜。

因为先手随便拿一个石头,石头总数变为 S − 1 S-1 S1, S S S是奇数, ⌊ S 2 ⌋ \\lfloor \\fracS2 \\rfloor 2S = ⌊ S − 1 2 ⌋ \\lfloor \\fracS-12 \\rfloor 2S1 , 所以所有的石头堆的个数还是小于 ⌊ S 2 ⌋ \\lfloor \\fracS2 \\rfloor 2S S S S变为偶数,情况转为第二种情况,只是这个时候后手面临这种情况,那后手就必败。

代码:

/*
 * @file D.cpp
 * @path D:\\code\\ACM\\codeforces\\Div2_666\\D.cpp
 * @author Xiuchen
 * @date  2020-09-23 21:51:57
*/

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<math.h>
#include<iostream>
#include<algorithm>
//#define DEBUG
#define dbg(x) cout << #x << " = "<< (x) << endl
#define dbg2(x1,x2) cout << #x1 << " = " << x1 << " " << #x2 << " = " << x2 << endl
#define dbg3(x1,x2,x3) cout<< #x1 << " = " << x1 << " " << #x2 << " = " << x2 << " " << #x3 << " = " << x3 <<endl
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 110;
int gcd(int a, int b)
    return b ? gcd(b, a % b) : a;

int t, n;
int a[maxn];
int main()
#ifdef DEBUG
    freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
    scanf("%d", &t);
    while(t--)
        scanf("%d", &n);
        int sum = 0;
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]), sum += a[i];
        sort(a + 1, a + n + 1);
        if(a[n] > sum / 2) printf("T\\n");
        else
            if(sum % 2 == 0) printf("HL\\n");
            else printf("T\\n");
        
    
    return 0;

以上是关于CF 666 (Div. 2) D. Stoned Game博弈论的主要内容,如果未能解决你的问题,请参考以下文章

CF #375 (Div. 2) D. bfs

CF #374 (Div. 2) D. 贪心,优先队列或set

CF-Div2-832 D. Yet Another Problem(bitmask&结论)

CF-Div2-832 D. Yet Another Problem(bitmask&结论)

CF #404 (Div. 2) D. Anton and School - 2 (数论+范德蒙恒等式)

CF #727(div2)D. PriceFixed, 贪心,双指针