CF# 334 Lieges of Legendre
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:
- Remove a single cow from a chosen non-empty pile.
- 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.
The first line of the input contains two space-separated integers n and k (1 ≤ n ≤ 100 000, 1 ≤ k ≤ 109).
The second line contains n integers, a1, a2, ... an (1 ≤ ai ≤ 109) describing the initial state of the game.
Output the name of the winning player, either "Kevin" or "Nicky" (without quotes).
2 1
3 4
Kevin
1 2
3
Nicky
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,k,表示有n堆石子,石子数目分别为a1.a2...an,
每次一个人可以在任意一堆拿掉一个石子,或者,如果某堆石子是偶数个的话,设为2*x个,可以分为k堆x个的石子
取得最后一颗石子即为胜利。
问先手赢还是后手赢。
分析:显然,根据sg函数的定义,sg函数定义为当前状态第一个达不到的状态。
其中,石子游戏用石子数目当作当前状态。
如果有多堆石子,则将它们异或起来。
显然,如果k是偶数的话,考虑一堆的情况,那么奇数必胜,偶数必败,这个可以用数学归纳法证明。那么如果有多堆的情况就考虑一下奇数堆和偶数堆的数目即可。
如果k为奇数,就按照sg函数的定义做就好。
1 /** 2 Create By yzx - stupidboy 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cmath> 8 #include <deque> 9 #include <vector> 10 #include <queue> 11 #include <iostream> 12 #include <algorithm> 13 #include <map> 14 #include <set> 15 #include <ctime> 16 #include <iomanip> 17 using namespace std; 18 typedef long long LL; 19 typedef double DB; 20 #define MIT (2147483647) 21 #define INF (1000000001) 22 #define MLL (1000000000000000001LL) 23 #define sz(x) ((int) (x).size()) 24 #define clr(x, y) memset(x, y, sizeof(x)) 25 #define puf push_front 26 #define pub push_back 27 #define pof pop_front 28 #define pob pop_back 29 #define mk make_pair 30 31 inline int Getint() 32 { 33 int Ret = 0; 34 char Ch = ' '; 35 bool Flag = 0; 36 while(!(Ch >= '0' && Ch <= '9')) 37 { 38 if(Ch == '-') Flag ^= 1; 39 Ch = getchar(); 40 } 41 while(Ch >= '0' && Ch <= '9') 42 { 43 Ret = Ret * 10 + Ch - '0'; 44 Ch = getchar(); 45 } 46 return Flag ? -Ret : Ret; 47 } 48 49 int n, k, state; 50 51 inline int Sg(int x) 52 { 53 if(k & 1) 54 { 55 if(x < 5) 56 { 57 if(x == 4) return 2; 58 if(x == 2 || x == 0) return 0; 59 return 1; 60 } 61 if(x & 1) return 0; 62 return Sg(x / 2) == 1 ? 2 : 1; 63 } 64 else 65 { 66 if(x == 1) return 1; 67 if(x == 2) return 2; 68 return (x & 1) ^ 1; 69 } 70 } 71 72 inline void Input() 73 { 74 scanf("%d%d", &n, &k); 75 for(int i = 0; i < n; i++) 76 { 77 int x; 78 scanf("%d", &x); 79 state ^= Sg(x); 80 } 81 } 82 83 inline void Solve() 84 { 85 puts(state ? "Kevin" : "Nicky"); 86 } 87 88 int main() 89 { 90 freopen("a.in", "r", stdin); 91 Input(); 92 Solve(); 93 return 0; 94 }