【题解】
题意:两个人轮流出牌,每次出牌的颜色不能跟对方出过的牌的颜色一致,如果谁出不了牌就输了。
思路:每个人优先出的牌的颜色肯定是:场上没出过的, 对方也持有的,并且两个人手中持有数量最多的牌。对方持有的越多意味着可以封掉更多的牌,而自己手里的越多意味着可以防止自己更多的牌被封掉。因此,对所有的两个人手里都持有的颜色的牌数进行统计, 从大到小依次分配给第一、二个玩家。如果此时第一个玩家手里的牌数 > 第二个玩家,则第一个玩家胜利, 否则第二个玩家胜利。 到此为止,问题转换成另一个问题:有一堆东西,每个东西有两个值,A 拿到这个东西的收益是 ai,B 拿到的收益是 bi,两人依次拿,求最优策略下两人的各自收益。这是一个经典问题,答案就是按照 ai + bi 排序模拟一下就好了。
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int N=2e5+10;
P A[N],B[N],C[N];
ULL a[N];
ULL k1,k2;
ULL rng(){
ULL k3=k1,k4=k2;k1=k4;k3^=k3<<23;k2=k3^k4^(k3>>17)^(k4>>26);
return k2+k4;
}
void init(P T[],int& n,int p)
{
if(p==1){
for(int i=0;i<n;i++) scanf("%llu",&a[i]);
}
else{
int mod; scanf("%llu%llu%d",&k1,&k2,&mod);
for(int i=0;i<n;i++) a[i]=rng()%mod;
}
sort(a,a+n);
int l=0;
for(int i=0,j=0;i<n;i=j){
while(j<n&&a[j]==a[i]) j++;
T[l++]=P(a[i],j-i);
}
n=l;
}
bool cmp(const P& a, const P& b)
{
return a.first+a.second>b.first+b.second;
}
int main()
{
int T; scanf("%d",&T);
while(T--){
int n,m,p; scanf("%d%d%d",&n,&m,&p);
init(A,n,p); init(B,m,p);
int SA=0,SB=0,k=0;
int p1=0,p2=0;
while(p1<n||p2<m){
if(p1<n&&p2<m&&A[p1].first==B[p2].first) C[k++]=P(A[p1++].second,B[p2++].second); //双方手里的相同颜色的牌的数目
else if(p1==n||(p2<m&&A[p1].first>B[p2].first)) SB+=B[p2++].second; //如果B[p2].first比较小,那么说明不可能有相同颜色了
else if(p2==m||(p1<n&&A[p1].first<B[p2].first)) SA+=A[p1++].second; //同上,所以直接加上贡献,这是互不影响的
}
sort(C,C+k,cmp); //按照贡献和排序
for(int i=0;i<k;i++){
if(i%2==0) SA+=C[i].first;
else SB+=C[i].second;
}
if(SA>SB) puts("Cuber QQ"); //Cuber QQ 先手
else puts("Quber CC");
}
return 0;
}