題目
思路
有一個顯而易見的結論,如果我可以將其分成對稱的,那麼先手必敗。
比如,我們有 的石子。顯然這是對稱的,那麼對手如何操作,我只要對稱的操作即可。
現在,我們考慮不對稱的情況。如果某些堆是不能配對的,那麼它們一定兩兩不相同。
我們來分類討論一下吧!——
- 如果有奇數堆石子。
在數軸上將每一堆石子的數量點出來,大致就是
那麼,我把最大的那一堆用來填補紅色的部分,就可以變成兩兩匹配的情況。
填補完之後,顯然,這一堆還會剩下一些(在數軸上可以很直觀的看出, 是把紅色部分包含在內的,並且 和第二大之間至少有 的距離)。
剛好,把這些剩下的拿完,就滿足了拿石子的要求:至少拿走一個,然後分給別人一些。
- 如果有偶數堆石子。
直接將數軸的原點設置爲 即可——將 轉變爲 ,順便填補其餘的。
顯然,利用原點 “吃掉” 一個點之後,剩下的就是奇數堆石子,與上面一樣了。
- 綜上所述!
只要不是兩兩匹配,就是先手勝,否則後手勝。
代碼
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
inline int readint(){
int a = 0, f = 1; char c = getchar();
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
inline void writeint(long long x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) writeint(x/10);
putchar((x%10)^48);
}
# define MB template < typename T >
MB void getMax(T &a,const T &b){ if(a < b) a = b; }
MB void getMin(T &a,const T &b){ if(b < a) a = b; }
const int MaxN = 201, infty = (1<<30)-1;
int a[MaxN], n;
int main(){
while(scanf("%d",&n) != EOF){
if(n == 0) break;
for(int i=1; i<=n; ++i)
a[i] = readint();
sort(a+1,a+n+1), a[n+1] = infty;
bool win = false;
for(int i=1; i<=n and not win; i+=2)
if(a[i] != a[i+1])
win = true;
printf("%d\n",win);
}
return 0;
}