H - Split Game ( sg博弈 )
sg博弈原理推荐阅读:https://blog.csdn.net/strangedbly/article/details/51137432
For a long time, rich clientele of Binary Casino has been requesting a new way to gamble their money. To fulfill their wishes, the director of Binary Casino decided to introduce a new game called Split Your Tokens.
This game is played only when a customer is about to exit the casino. Instead of exchanging tokens won during his visit, he may take up casino's challenge and bet all of his earned tokens on winning this game. Should the customer lose, all of his tokens are lost in favor of the casino.
When the game starts, the customer splits his tokens into N
piles with not necessarily same amount of tokens in each pile. The customer and the casino then exchange turns in this game we denote the customer as the first player and the casino as the second player. Each player in his turn decides which pile he wants to split and chooses a positive integer K which is smaller than the size of the selected pile. Then the player splits the selected pile into as many piles of size K
as possible. If any tokens remain, they form another pile on their own. A player loses the game when he can not do any more splitting. The customer (first player) always plays first.
The director of Binary Casino is however not sure, whether this game will be profitable for the casino in the long term. Your task is thus to determine, for a given configuration of piles, which player wins when both players play optimally.
Input
The first line contains one integer N
(1≤N≤2000), the number of piles. The second line contains a sequence of N integers Pi (1≤Pi≤2000), Pi represents the number of tokens in the i
-th pile.
Output
Output a single line with either "First" or "Second", depending on which player wins the game if both play optimally.
Examples
Input
3 1 2 3
Output
First
Input
3 1 2 2
Output
Second
题意:有n堆石子,两个人轮流操作,选择第 i 堆石子,再选择一个数 k ( k小于第 i 堆的石子数 )把第i堆石子尽可能的分成k个一堆, 例如:8个石子,选择k=3, 那么分成三堆分别是 3 3 2 。
思路: 先对一堆预处理sg函数,多堆的直接取异或值。
代码:
#include <bits/stdc++.h>
using namespace std;
int sg[2005];
int via[2005];
void get_sg()
{
sg[1] = 0;
for ( int i=2; i<=2000; i++ ) { // 这一堆石子个数
memset(via,0,sizeof(via));
for ( int k=1; k<i; k++ ) { // 选择的k值, 注意小于i
int now = i;
int ans = 0;
while ( now>0 ) {
if ( now>=k ) ans^=sg[k];
else ans^=sg[now];
now -= k;
}
via[ans] = 1;
}
for ( int j=0; j<=2000; j++ ) {
if ( via[j]==0 ) {
sg[i] = j;
break;
}
}
}
}
int main()
{
get_sg();
int x,n,i,ans=0;
cin >> n;
for ( i=0; i<n; i++ ) {
cin >> x;
ans ^= sg[x];
}
if ( ans==0 ) cout << "Second" << endl;
else cout << "First" << endl;
return 0;
}