K. Alice and Bob-2 题解(sg函数)
题目链接
题目思路
我感觉这种对于多堆石子的好像都是这个套路,求sg函数,然后异或
下面为官方题解
容易发现,对于一个字符串而言,玩家的胜负与具体字母无关,只和这些字母的出现次数有关。
在 n ≤ 40 时,这样本质不同的状态一共有P(i) = 215308 种,其中 P(i) 表示 i 的无序分拆数。
记忆化搜索或拓扑序遍历所有可能的状态求得每个字符串对应的 SG 函数。
当所有字符串的 SG 函数值异或和为 0 时,先手必败。
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=5e3+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n;
char s[maxn];
map<vector<int>,int> mp;
int dfs(vector<int> cur){
if(mp.count(cur)){
return mp[cur];
}
set<int> se;
for(int i=0;i<26;i++){
if(cur[i]==0) continue;
vector<int> nxt(cur);
nxt[i]--;
sort(nxt.begin(),nxt.end());
se.insert(dfs(nxt));
for(int j=i+1;j<26;j++){
if(cur[j]==0) continue;
vector<int> nxt(cur);
nxt[i]--;
nxt[j]--;
sort(nxt.begin(),nxt.end());
se.insert(dfs(nxt));
}
}
for(int i=0;;i++){
if(!se.count(i)){
return mp[cur]=i;
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int _;cin>>_;
while(_--){
int ans=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>s+1;
int len=strlen(s+1);
vector<int> cnt(26,0);
for(int j=1;j<=len;j++){
cnt[s[j]-'a']++;
}
sort(cnt.begin(),cnt.end());
ans^=dfs(cnt);
}
printf(ans!=0?"Alice\n":"Bob\n");
}
return 0;
}
不摆烂了,写题