Codeforces Gym 100379G Wythoff’s game with three piles 博弈

题目大意:

就是现在3堆石子, 每次操作从其中一堆拿走任意数量的石子, 或者从同时3堆中拿走同样数量的石子, 每次操作拿的石子数量至少是1颗

两人轮流进行操作

拿走最后一颗石子的人胜

对于给出的三堆石子的数量a, b, c <= 1e12, 判断谁会获得胜利, 如果先手胜利输出必胜的第一步, 任意一种即可


大致思路:

这个题表示看了半天觉得好像和3堆的Nim博弈没有区别就直接当Nim博弈做了...然后就AC了....

不过还是需要证明的

为了证明这和Nim博弈是一个东西, 需要证明SG值没有变化, 而证明SG值没有变化的关键就在于原本SG为0的点不能到达SG不为0的点

也就是要证明如果有 a^b^c == 0那么不存在 0 < t <= min(a, b, c)使得(a - t)^(b - t)^(c - t) == 0


这个的证明要感谢hust的zk提供的一个证明思路:考虑正整数 t 在二进制表示下的最低位的1

对于这个位置, 一个数n 减去 t , 这一位要么从0变成1要么从1变成0

而a - t, b - t, c - t由于满足a^b^c == 0那么 a, b, c中这个位的值要么是(0, 0, 0)要么是(1, 1, 0)

于是a - t, b - t, c - t就是1, 1, 1或者0, 0, 1那么异或值一定不是0

也就是说原本Nim游戏中的SG值是0的部分不会改变

那么就可以按照原本Nim游戏的必胜方式获胜了, 每次走到异或值为0的状态着胜

于是判断初始a^b^c的值即可判断谁获胜, 第一步自然是那成异或值为0的局面即可


代码如下:

Result  :  Accepted     Memory  :  4 KB     Time  :  60 ms

/*
 * Author: Gatevin
 * Created Time:  2015/8/14 19:08:31
 * File Name: Sakura_Chiyo.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

int main()
{
    int t;
    lint a, b, c;
    //scanf("%d", &t);
    cin>>t;
    while(t--)
    {
        //scanf("%I64d %I64d %I64d\n", &a, &b, &c);
        cin>>a>>b>>c;
        if((a^b^c) == 0)
            puts("2");
        else
        {
            printf("1 ");
            if(a > (b^c))
            {
                printf("1 %I64d\n", a - (b^c));
                continue;
            }
            if(b > (a^c))
            {
                printf("2 %I64d\n", b - (a^c));
                continue;
            }
            if(c > (a^b))
            {
                printf("3 %I64d\n", c - (a^b));
                continue;
            }
        }
    }
    return 0;
}






你可能感兴趣的:(codeforces,Gym,100379G)