【BestCoder Round #93】hdu6020 MG loves apple

探讨了如何通过移除序列中的K个元素使剩余序列模3等于0的问题,涉及计数不同余数的苹果数量并确保不存在前导零。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description MG is a rich boy. He has n apples, each has a
value of V(0<=V< =9).

A valid number does not contain a leading zero, and these apples have
just made a valid N digit number.

MG has the right to take away K apples in the sequence, he wonders if
there exists a solution: After exactly taking away K apples, the valid
N−K digit number of remaining apples mod 3 is zero.

MG thought it very easy and he had himself disdained to take the job.
As a bystander, could you please help settle the problem and calculate
the answer?

Input The first line is an integer T which indicates the case
number.(1<=T<=60)

And as for each case, there are 2 integer N(1<=N<=100000),K(0<=K< N) in
the first line which indicate apple-number, and the number of apple
you should take away.

MG also promises the sum of N will not exceed 1000000。

Then there are N integers X in the next line, the i-th integer means
the i-th gold’s value(0<=X<=9).

Output As for each case, you need to output a single line.

If the solution exists, print”yes”,else print “no”.(Excluding
quotation marks)

首先知道问题等价于剩下的数字和是3的倍数。
扫描一遍,记下0、余数是1、余数是2、余数是0且非0的个数,以及第一个出现的后三者之前有多少个0
枚举余数是2的数删掉多少个,可以求出要保证不越界,对应的余数是1的数需要删掉的个数的范围。接下来考虑不能有前导零,这就需要保证余数是1或者余数是2或者余数是0且非0中至少有一个没有被删干净,而且之前的0的个数比删掉的0的个数少【因为0一定从前往后删,非0的数一定从后往前删】。
说起来很麻烦,但是代码不难写。注意特判只剩下0的情况,这也是合法的。
感觉官方题解做法很繁琐,而且有问题,比如数据

6 2
201011

当然也可能是我理解错了意思。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[100010];
int a[100010],n,k;
bool solve()
{
    int cnt0=0,cnt1=0,cnt2=0,cnt369=0,before1=0,before2=0,before369=0,sum,x,mnj,mxj;
    scanf("%d%d",&n,&k);
    scanf("%s",s+1);
    for (int i=1;i<=n;i++) a[i]=s[i]-'0';
    for (int i=1;i<=n;i++)
    {
        if (a[i]%3==1) cnt1++;
        if (a[i]%3==2) cnt2++;
        if (a[i]%3==0)
        {
            if (!a[i])
            {
                cnt0++;
                if (!cnt1) before1++;
                if (!cnt2) before2++;
                if (!cnt369) before369++;
            }
            else cnt369++;
        }
    }
    sum=(cnt1+cnt2*2)%3;
    if (k==n-1&&cnt0+cnt369) return 1;
    for (int i=0;i<=cnt2;i++)
    {
        x=((sum-2*i)%3+3)%3;
        mnj=max(0,k-i-cnt0-cnt369);
        mxj=min(cnt1,k-i);
        while (mnj%3!=x) mnj++;
        while (mxj>=0&&mxj%3!=x) mxj--;
        if (mnj>mxj) continue;
        if (before369<=k-i-mnj) return 1;
        if (mnj<cnt1&&before1<=k-i-mnj) return 1;
        if (i<cnt2&&before2<=k-i-mnj) return 1;
    }
    return 0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
        if (solve()) printf("yes\n");
        else printf("no\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值