石子游戲

【百度筆試題 20.03.29,源自Codeforces Round #573 (Div. 1)

有n堆石子,每堆有a[i]個石子。男、女兩個人輪流取,每次從任意一個堆中取一個石子。

當一個人取之前所有堆都是空的,或者取之後存在兩個堆的石子數量相同(可能都爲空),則這個人輸。

男的先取,兩人取石子都使用對自己最有利的策略,輸出最後的贏家。

輸入:
第一行T, 表示樣例數
對於每組樣例, 第一數爲n, 後面n個數爲每堆的石子數量

輸出:
每組樣例的贏家

樣例輸入:
2
1 [0]
2 [2,2]

樣例輸出:
woman
man

【思路】

先判斷先手能否走第一步,以下情況不能:

  1. 全爲0
  2. 如果一個數出現了3次 (取之後必然有兩個堆相同)
  3. 至少有2個數字出現次數\geq2 (取之後必然有兩個堆相同)

如果先手能走第一步,最後一定會形成 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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章