牛客练习赛43 F Tachibana Kanade Loves Game 容斥定理

题目链接:

https://ac.nowcoder.com/acm/contest/548/F

思路:

尽量选伤害对手而不伤害自己的武器,如果这些武器用完了,就选既伤害自己又伤害对手的武器。

选不伤害自己的武器其实就是选不是2,3...m的倍数,这其实可以进一步推出选不是2--m中的素数的倍数,因为每一个数都可以被表示成素数相乘。

找不是2-m中素数的倍数其实可以用n减去2-m素数的并集,这里就需要用容斥定理了。

可以通过dfs来取容斥定理所需要的集合,然后套用容斥定理公式即可。

还有几个优化:

(1)如果自身血量==0,则直接算输。

(2)如果自己的武器数小于敌人血量则算输。

求出总数sum之后,n-sum就是不伤害自己的总数。

如果n-sum>=k赢。

否则则需要伤害自己的武器补伤害,如果伤害不够或者补着补着自己就死了则算输。

否则算赢

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll k,q,n,m;
int su[15]={0,2,3,5,7,11,13,17,19};
int vis[15];
int re[15];
ll sum;
int r;
void dfs(int loc,int nn,int nnum)
{
    if(nnum==nn)
    {
        ll tsum=1;
        for (int i=0;i<nn;i++)
        {
            tsum*=su[re[i]];
        }
        if(nn%2) sum=sum+n/tsum;
        else sum=sum-n/tsum;
        return;
    }
    for (int i=loc;i<=r;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            re[nnum]=i;
            dfs(i+1,nn,nnum+1);
            vis[i]=0;
        }
    }
}
int main()
{

    while(scanf("%d",&t)!=EOF)
    {
        while(t--)
        {
            scanf("%lld%lld%lld%lld",&k,&q,&n,&m);
            sum=0;
            if(k==0||q>n)
            {
                printf("QAQ\n");
                continue;
            }
            r=0;
            for (int i=1;i<=8;i++)
            {
                if(m<su[i]) break;
                r++;
            }
            for (int i=1;i<=r;i++)
            {
                memset (vis,0,sizeof(vis));
                dfs(1,i,0);
            }
            if(n-sum>=q)
            {
                printf("Yes\n");
                continue;
            }
            q=q-(n-sum);
            if(sum<q||k<q)
            {
                printf("QAQ\n");
            }
            else
            {
                printf("Yes\n");
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/89073706
今日推荐