codeforces603CLieges of Legendre+SG博弈

Kevin and Nicky Sun have invented a new game called Lieges of Legendre. In this game, two players take turns modifying the game state with Kevin moving first. Initially, the game is set up so that there are n piles of cows, with the i-th pile containing ai cows. During each player’s turn, that player calls upon the power of Sunlight, and uses it to either:

1. Remove a single cow from a chosen non-empty pile.
2.Choose a pile of cows with even size 2·x (x > 0), and replace it with k piles of x cows each. 

The player who removes the last cow wins. Given n, k, and a sequence a1, a2, …, an, help Kevin and Nicky find the winner, given that both sides play in optimal way.
Input

The first line of the input contains two space-separated integers n and k (1 ≤ n ≤ 100 000, 1 ≤ k ≤ 10^9).

The second line contains n integers, a1, a2, … an (1 ≤ ai ≤ 10^9) describing the initial state of the game.
Output

Output the name of the winning player, either “Kevin” or “Nicky” (without quotes).
Examples
Input

2 1
3 4

Output

Kevin

Input

1 2
3

Output

Nicky

Note

In the second sample, Nicky can win in the following way: Kevin moves first and is forced to remove a cow, so the pile contains two cows after his move. Next, Nicky replaces this pile of size 2 with two piles of size 1. So the game state is now two piles of size 1. Kevin then removes one of the remaining cows and Nicky wins by removing the other.

题意:有n堆石子。两个人轮流取石子,取法有两种。1,从一堆中取走一个,2.取一个2*x(x>0)堆,即一个偶数堆变成k堆,每堆x个石子(并不是将2*x分解,而是召唤了太阳能量。变成了k个x个的堆)。。。
解法:巴拉巴拉!太阳能量+SG。。。。
首先我们考虑分解成k堆,,如果k是偶数,先手分解之后,那么采用对称博弈。后手怎么做,先手就怎么做,一定能赢,跟一堆没有一样。。完了。如果k是奇数,也是对称博弈。除了一堆以外,其实就相当于只有一堆。。也完了。。直接将k=k%2;来考虑就好了。。。。
然后我们打个表发现以下就好了。。
等等!别跑。。(打表有个卵啊,k==0还好说。。k==1啥规律没看出来。)
巴拉巴拉!垃圾能量。好吧。(k==1的规律就是,要么是1,要么是2.4位以后的奇数为是0)(要么1?要么2?到底是什么呢???T_T)

SG打表部分代码。。这个会吧。。。
visit[getSG(n-1)]=true;
 if(n%2==0){
     if(k==0) visit[getSG(0)]=true;
     else visit[getSG(n/2)]=true;
}

前几项,以及奇数直接返回了。。我们来考虑n是偶数时
visit[getSG(n-1)]=true;。。此时visit[0]=true;
那么getSG(n/2)是多少呢?是2?那么visit[1]就是0咯!是1?那么visit[2]就是0咯!直接递归调用。。完了。。。
先SG的模板打表,找到规律后再打SG表。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define LL long long

using namespace std;
int k,a;
//int SG[1000];
int getSG(int n){
    if(n==0) return 0;
    if(k==0){
        if(n==1) return 1;
        else if(n==2) return 2;
        else if(n%2==1) return 0;

        int x=getSG(0);
        if(x==1) return 2;
        else return 1;
    }
    else{
        if(n==1) return 1;
        else if(n==2) return 0;
        else if(n==3) return 1;
        else if(n==4) return 2;
        else if(n%2==1) return 0;

        int x=getSG(n/2);
        if(x==1) return 2;
        else return 1;
    }
}
int main(){
    int ans=0,n;
    scanf("%d %d",&n,&k);
    k=k%2;
    for(int i=1;i<=n;i++){
        scanf("%d",&a);
        ans^=getSG(a);
    }
    if(ans) printf("Kevin\n");
    else printf("Nicky\n");
    return 0;
}

SG的模板打表代码。。。打完再写的上边那么打表。。
/*
int getSG(int n){
    if(n==0) return 0;
    if(n==1) return 1;
    if(SG[n]!=-1) return SG[n];
    bool visit[10000];
    memset(visit,0,sizeof(visit));


    visit[getSG(n-1)]=true;
    if(n%2==0){
        if(k==0) visit[getSG(0)]=true;
        else visit[getSG(n/2)]=true;
    }
    for(int i=0;;i++){
        if(visit[i]==0){
            return SG[n]=i;
        }
    }
}
    */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值