hdu 6020 MG loves apple //bc Round #93 1002

MG loves apple

 
 Accepts: 20
 
 Submissions: 693
 Time Limit: 3000/1500 MS (Java/Others)
 
 Memory Limit: 262144/262144 K (Java/Others)
问题描述
MGMG是一个财富爆表的男孩子。他拥有N(1<=N<=100000)N(1<=N<=100000)个苹果,每个苹果上标有一个数字00~99,代表它的价值。

一个合法的数字是不含有前导零的,这nn个苹果恰好排成了一个合法的NN位数。

MGMG拥有拿去KK个苹果的权利(0<=K<0<=K<NN)。
他想知道是否存在方案,使得恰好拿去KK个苹果后,序列中剩下的苹果排成的合法数字模33等于零。数据保证所有NN之和不超过10000001000000.

MGMG认为这件事非常容易,不屑于用计算机解决,于是运用他高超的人类智慧开始进行计算。作为一名旁观者,你也想挑战MGMG智慧,请你写个程序,计算答案。
输入描述
第一行一个整数TT,代表数据组数(1 <=T<=601<=T<=60)。
接下来,对于每组数据——
第一行两个个整数NN,KK,表示苹果序列长度,以及需要拿去的苹果个数.
接下来一行NN个整数XX,表示每个苹果的价值(0<=X<=90<=X<=9)。
输出描述
对于每一组数据,输出一行。
若方案存在,则输出“yes”,否则输出“no”。(输出不包含引号)
输入样例
2
5 2
11230
4 2
1000 
输出样例
yes
no

官方题解写的方法就很好。。。。

我们设S0S0S1S1S2S2分别为原串上mod 3=0mod3=01122数字的个数。 我们假定删除取模后为001122的数字各AABBCC个,则显然有0<=A<=S0,0<=B<=S1,0<=C<=S20<=A<=S0,0<=B<=S1,0<=C<=S2K=A+B+CK=A+B+CSumSum mod 3=(A*0+B*1+C*2)mod 3=(S0*0+S1*1+S2*2)mod 3=biasmod3=(A0+B1+C2)mod3=(S00+S11+S22)mod3=bias。 枚举CC的值,我们可得B mod 3=(bias-C*2)mod 3,A=K-B-CBmod3=(biasC2)mod3,A=KBC。如果有若干组A,BA,B不逾界,可知这些(A,B,C)(A,B,C)是在模意义下合法的解,但不一定满足没有前导零。

所以,对于【大于00的数】我们贪心地从后往前删除,对于00我们贪心地从前往后删除。

需要统计出:a3a3=第一个【mod 3=0mod3=0且非00的数】前00的个数(如果mod 3=0mod3=0且非00的数不存在,那么a3a3就取所有零的个数),E1E1=【第一个00前是否存在mod 3=1mod3=1的数】,E2E2=【第一个00前是否存在mod 3=2mod3=2的数】。

则以下情况满足任一种都能保证无前导零:A>=a3A>=a3B<B<S1S1E1E1C<C<S2S2E2E2



不过要加一个特判,当删n-1个时,留一个0是可以的

当时很不理解为什么满足“A>=a3B<B<S1S1E1E1C<C<S2S2E2E2”其中之一就一定成立

后来举了好多例子,发现确实是
这里假设0为等于零的数,1为模三等于1的数,2为模三等于2的数,3为模三等于3且非零的数

最开始数为合法数字

第一位肯定是1或2或3

是3时,要么把0,3全部删掉,这样肯定不会有前导零,要么不全删,这样我只要保留第一个3就不会出现前导零

所以是3时,肯定不会出现前导零的情况,而第一位是3一定满足A>=a3的条件

是2时,不全删,保留第一个2,肯定不会出现前导零,这个时候满足c<s2的条件

全删掉时,只有当“A>=a3B<B<S1S1E1E1”至少有一个条件成立时就不会出现前导零,否则就会出现

是1时同理

#include<bits/stdc++.h>
using namespace std;
int num[100005];
int main()
{
    int z,t,n,k,i,j,xx[3];
    char c;
    scanf("%d",&t);
    while(t--)
    {
        i=0;
        scanf("%d %d",&n,&k);
        getchar();
        xx[0]=xx[1]=xx[2]=0;
        int sum=0;
        int flog=0,flag=0,zero=0,flag1=0,flag2=0;
        for(i=0;i<n;i++)
        {
            c=getchar();
            num[i]=c-'0';
            if(num[i]%3==0&&!flog)
             {
                if(num[i]==0)
                {
                    zero++;
                    flag=1;
                }
                else
                    flog=1;
            }
            if(!flag)
            {
                if(num[i]%3==1)
                    flag1=1;
                else if(num[i]%3==2)
                    flag2=1;
            }
            sum=(sum+num[i])%3;
            xx[num[i]%3]++;
        }
        bool ok=0;
        if(k==n-1)
        {

             for(i=0;i<n;i++)
             if(num[i]%3==0)
                ok=1;
             if(ok)
                printf("yes\n");
             else
                printf("no\n");
             continue;
        }
        for(i=0;i<=xx[2];i++)
        {
            for(j=((sum-i*2)%3+3)%3;j<=xx[1];j+=3)
           // for(j=0;j<=xx[1];j++)
            {
             //   if((i*2+j*1)%3==sum)
              //  {
                    z=k-i-j;
                    if(z<=xx[0]&&z>=0)
                    {
                        if(z>=zero)
                        ok=1;
                        if(j<xx[1]&&flag1)
                        ok=1;
                        if(i<xx[2]&&flag2)
                        ok=1;
                        if(ok)
                        break;
                    }
             //   }
            }
            if(ok)
                break;
        }
        if(ok)
            printf("yes\n");
        else
            printf("no\n");
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值