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;
}


posted @ 2021-09-22 20:25  hunxuewangzi  阅读(118)  评论(0编辑  收藏  举报