【百度筆試題 20.03.29,源自Codeforces Round #573 (Div. 1)】
有n堆石子,每堆有a[i]個石子。男、女兩個人輪流取,每次從任意一個堆中取一個石子。
當一個人取之前所有堆都是空的,或者取之後存在兩個堆的石子數量相同(可能都爲空),則這個人輸。
男的先取,兩人取石子都使用對自己最有利的策略,輸出最後的贏家。
輸入:
第一行T, 表示樣例數
對於每組樣例, 第一數爲n, 後面n個數爲每堆的石子數量
輸出:
每組樣例的贏家
樣例輸入:
2
1 [0]
2 [2,2]
樣例輸出:
woman
man
【思路】
先判斷先手能否走第一步,以下情況不能:
- 全爲0
- 如果一個數出現了3次 (取之後必然有兩個堆相同)
- 至少有2個數字出現次數2 (取之後必然有兩個堆相同)
如果先手能走第一步,最後一定會形成 0,1,2,3,4...n-1的局面(順序不一定), 因爲大的數不可能越過比它小的數(即任意兩個堆的大小關係不會變)
當一個人取之前達到了這種局面,必輸。只需要根據達到這種局面需要的步數的奇偶,判斷誰會碰到這種局面即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100050;
int a[maxn];
map<int,int>mp;
int main(){
int n,t;
scanf("%d",&t);
while(t--){
mp.clear();
scanf("%d",&n);
ll sum=0; // 達到0,1,2...,n-1這個局面時需要的步數
int flag=0, num=0, cnt0=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mp[a[i]]++;
if(a[i]==0) cnt0++; // 統計0的個數,若全爲0則先手輸
if(mp[a[i]]==2) num++; // 統計至少出現2次的數字個數
if(mp[a[i]]>2) flag=1; // 存在至少出現3次的數字
sum += a[i];
sum -= (i-1);
}
if(flag || num>=2 || cnt0==n){
printf("woman\n");
continue;
}
if(sum%2) printf("man\n");
else printf("woman\n");
}
return 0;
}