Codeforces Round #334 (Div. 1) C. Lieges of Legendre

Lieges of Legendre

题意:有n堆牛,每堆有ai头牛。两个人玩一个游戏,游戏规则为:

<1>从任意一个非空的堆中移走一头牛;

<2>将偶数堆2*x变成k堆,每堆x头牛(可以增加牛的个数)

移走最后一头牛的人获胜;

数据:n and k (1 ≤ n ≤ 100 000, 1 ≤ k ≤ 109).a1, a2, ... an (1 ≤ ai ≤ 109)

分析:这显然是SG函数与SG定理的应用;

SG函数与SG定理:SG[x] = mex(S);其中S是所有x的后继状态SG函数值的集合,mex(S) 表示不在S内的最小非负整数SG[x] = 0当且仅当x为必败状态

游戏和的SG函数等于各子游戏的SG函数的nim和(nim和就是异或操作)

理解:对于初始的状态要求出SG函数值,就必须等到所有的子状态的SG函数,但是由于ai的值太大(是对操作1而言的),这是一般需要打表找出规律;即数组ret的两维表示k偶奇时前5个值的SG值,并且容易发现不论k的奇偶,当i >= 5 且 i为奇数时,ai = 0;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
    T x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
int k;
int ret[][5] = {{0,1,2,0,1},{0,1,0,1,2}};
int mex(int state)
{
    if(state < 5) return ret[k%2][state];// G[0] = 0,G[1] = 1;
    int a,b;
    if(state & 1){
        return 0;
    }else{
        if(k & 1) b = mex(state/2);
        else b = 0;
        a = 0;// mex(state - 1) = 0;
        if(a != 0 && b != 0) return 0;
        if(a != 1 && b != 1) return 1;
        return 2;
    }
}
int main()
{
    int n,ans = 0,x;
    read2(n,k);
    rep1(i,1,n){
        read1(x);
        //ans = 0;
        ans ^= mex(x);//mex(i)用来找规律;
        //cout<<ans<<" ";
    }
    printf("%s",ans?"Kevin":"Nicky");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/hxer/p/5221582.html