題目鏈接
前置trick:
使用vector去重:
vector<int> a(n);for(int i=0;i<n;i++) cin>>a[i];sort(a.begin(),a.end());a.erase(unique(a.begin(),a.end()),a.end());n=a.size();
題意:
有 n n n堆石子,第 i i i堆有 a i a_i ai?顆。Alice 和 Bob 兩人輪流,Alice 先手。每一輪玩家從所有非空堆中拿走相同數量的石子,不能行動的失敗。若兩位玩家均使用最優策略,求最終獲勝者。
題解:
首先考慮如何簡化問題,由于是從所有非空堆拿走石頭,所以重復數量石頭堆可以去重。然后最少的石頭堆只有一個石頭的情況下只有一種操作,即所有石頭堆都取走一個石頭,直到沒有石頭或最少數量大于1的情況。在新的情況下,考慮從所有石子堆中取出一顆石子的新狀態為 S S S,若 S S S為必敗態,則當前狀態為必勝態。
否則, S S S的后繼狀態中必然存在必敗態,記為 S ′ S^{\prime} S′。我們發現 S S S的后繼狀態集合包含在當前狀態的后繼狀態集合中!這樣,當前狀態的后繼集合中必然存在必敗態,當前狀態就是必勝態。(好像是結論)那么只需要一開始模擬完最小堆為1的情況即可。
代碼:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define db double
const int mod=1e9+7;
const int N=4e5;
const db PI=acos(-1);
int T,n;signed main()
{std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>T;while(T--){cin>>n;vector<int> a(n);for(int i=0;i<n;i++) cin>>a[i];sort(a.begin(),a.end());a.erase(unique(a.begin(),a.end()),a.end());n=a.size();int sum=0;for(int i=0;i<n;i++){if(a[i]!=i+1) break;sum++;}if(a[n-1]==n) sum++;cout<<((sum%2==0)?"Alice":"Bob")<<"\n";}
}