HDU6655 Just Repeat

题意

两个人做游戏,先手有n张牌,后手有m张牌,每张牌有一种颜色,两人轮流出牌,当一个人出了一种颜色的牌之后,另一个人就不能出相同颜色的牌了,如果一个人无牌可出则输掉游戏。分别给出n张牌和m张牌的颜色,求赢家。
题目连接

思路

对于一个人有而另一个人没有的颜色可以不予考虑。到此为止, 问题转换成另一个问题,就是有一堆东西,每个东西有两个值,A 拿到这个东西的收益是 ai,B 拿到的收益是 bi。两人依次拿,求最优策略下两人的各自收益。解决方法是贪心,按照ai+bi排序,两人轮流拿。用交换法瞎证明一下不知对不对,设两个物品i,j,A取了i,B取了j,剩下的假设按照最优策略取,A得到suma权值,B得到sumb权值,若A取i,B取j的情况优于A取j,B取i。则有suma+ai-sumb-bj>suma+aj-sumb-bi。化简得ai+bi>aj+bj。

代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int maxn = 100000+10;

struct node
{
    int a,b;
};

int n,m,p;
ULL k1,k2;
int mo;
int a[maxn],b[maxn];
int tmp[2*maxn];
node c[2*maxn],d[2*maxn];
int ans1,ans2;
int num;

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

bool cmp(node x,node y)
{
    return x.a+x.b>y.a+y.b;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        if (p==1)
        {
            for (int i=1;i<=n;i++) scanf("%d",&a[i]);
            for (int i=1;i<=m;i++) scanf("%d",&b[i]);
        } else
        {
            scanf("%llu%llu%d",&k1,&k2,&mo);
            for (int i=1;i<=n;i++) a[i]=rng()%mo;
            scanf("%llu%llu%d",&k1,&k2,&mo);
            for (int i=1;i<=m;i++) b[i]=rng()%mo;
        }
        int nn=0;
        for (int i=1;i<=n;i++) tmp[++nn]=a[i];
        for (int i=1;i<=m;i++) tmp[++nn]=b[i];
        sort(tmp+1,tmp+nn+1);
        nn=unique(tmp+1,tmp+nn+1)-tmp-1;
        for (int i=1;i<=nn;i++) c[i].a=c[i].b=0;
        for (int i=1;i<=n;i++)
        {
            int pos=lower_bound(tmp+1,tmp+nn+1,a[i])-tmp;
            c[pos].a++;
        }
        for (int i=1;i<=m;i++)
        {
            int pos=lower_bound(tmp+1,tmp+nn+1,b[i])-tmp;
            c[pos].b++;
        }
        ans1=ans2=0;
        num=0;
        for (int i=1;i<=nn;i++)
        {
            if (c[i].a==0)
            {
                ans2+=c[i].b;
            } else
            if (c[i].b==0)
            {
                ans1+=c[i].a;
            } else
            {
                num++;
                d[num]=c[i];
            }
        }
        sort(d+1,d+num+1,cmp);
        for (int i=1;i<=num;i++)
        {
            if (i%2) ans1+=d[i].a; else ans2+=d[i].b;
        }
        if (ans1>ans2) printf("Cuber QQ
"); else printf("Quber CC
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhanggengchen/p/11436094.html