题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6655
题意:
小C和小Q玩起了打牌的游戏,两个人轮流出牌,小C先出,小C手中有n张牌,小Q有m张,两个人知道对方手中有什么牌,如果对手已经出过了这个数字,那么自己就不能再出这种数字的牌,问最后谁先不能出牌。
做法:
很明显如果一张牌只有自己有,那么这个肯定是自己能出的不用着急,关键的就是两个人共同有的牌。我们假设两个人共有10个1,8个2,小C现在有1个1和7个2并且他出,那么它肯定会先出1,这样的话对方就有9张牌不能出,哪怕自己之后的7个2都不能出,也是赚的。所以我们记录两个人都有的牌的总数,并且从大到小枚举,分别把牌给对应的人,最后再判断就好了。
严格说起来好像这道题也不算博弈了,就是个想法,贪心去做就好了,赛上的时候榜偏了导致这个题并没有被我们看到…无奈╮(╯▽╰)╭
代码:
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define ll long long
using namespace std;
const int maxn=100009;
typedef pair<int,int> pii;
unordered_map<int,int> mp;
int num[2][maxn<<1],a[maxn],b[maxn],mod;
int sum[2],n,m,p,ct;
vector<int> ve[maxn<<1];
unsigned long long k1, k2;
unsigned long long rng() {
unsigned long long k3 = k1, k4 = k2;
k1 = k4;
k3 ^= k3 << 23;
k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
return k2 + k4;
}
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int gain(int x){
if(!mp[x]) mp[x]=++ct;
return mp[x];
}
void init(){
rep(i,1,ct) num[0][i]=num[1][i]=0;
ct=0;
mp.clear();
}
int main(){
int t;scanf("%d",&t);
while(t--){
init();
scanf("%d%d%d",&n,&m,&p);
sum[0]=n,sum[1]=m;
if(p==1){
rep(i,1,n) {
a[i]=read();
int x=gain(a[i]);
num[0][x]++;
}
rep(i,1,m) {
b[i]=read();
int x=gain(b[i]);
num[1][x]++;
}
}
else{
cin>>k1>>k2>>mod;
rep(i,1,n) {
a[i]=rng()%mod;
int x=gain(a[i]);
num[0][x]++;
}
cin>>k1>>k2>>mod;
rep(i,1,m) {
b[i]=rng()%mod;
int x=gain(b[i]);
num[1][x]++;
}
}
int up=0;
rep(i,1,ct){
if(num[0][i]&&num[1][i]){
sum[0]-=num[0][i];
sum[1]-=num[1][i];
int mma=num[0][i]+num[1][i];
ve[mma].push_back(num[0][i]);
up=max(up,mma);
}
}
p=0;
for(int i=up;i>=1;i--){
for(auto v :ve[i]){
if(p==0) sum[0]+=v;
else sum[1]+=i-v;
p^=1;
}
ve[i].clear();
}
if(sum[0]>sum[1]) printf("Cuber QQ\n");
else printf("Quber CC\n");
}
return 0;
}