.http://acm.hdu.edu.cn/showproblem.php?pid=6020
BC题目质量高啊,可惜一个差不多得一个月才一场,,
思路:
首先可以想到将所有数字分对3取模,统计出余数为0,1,2的总数sum[3],接着进行穷举,对于选取了i个%3==2的数字和j个%3==1的数字,进行判断,是否合法,这里通过观察和总结,得出合法的条件如下:
假设sum0是指出现第一个x%3==0&&x!=0之前有多少个0的数量。
E1是指第一个0(或者没有出现)前有没有%3==1的数字出现。
E2是指第一个0(或者没有出现)前有没有%3==2的数字出现。
对于i,j,剩下选取0的个数为z=k-i-j,应满足:
(k-i-j>=sum0||(i<sum[2]&&E2)||(j<sum[1]&&E1))
穷举的所有情况只要有满足的则可以得到合法的数字,输出yes,否则输出no。
#include<bits/stdc++.h>
using namespace std;
int n,k,sum0,E1,E2,sum[3],sum_all;
char s[100005];
bool judge()
{
int mod=sum_all%3;
for(int i=0;i<=sum[2];i++)
{
for(int j=0;j<=sum[1];j++)
{
if(i+j>k) break;
if(k-i-j>sum[0]) continue;
if((i*2+j)%3!=mod)
continue;
if(k-i-j>=sum0||(i<sum[2]&&E2)||(j<sum[1]&&E1))
return true;
}
}
return false;
}
void cnt()
{
int flag1=1;
int flag2=1;
for(int i=0;s[i]!='\0';i++)
{
sum[(s[i]-'0')%3]++;
sum_all+=(s[i]-'0');
if(!(s[i]-'0')&&flag1)
{
sum0++;
flag2=0;
}
if((s[i]-'0')%3==1&&flag2)
E1=1;
if(((s[i]-'0')%3)==2&&flag2)
E2=1;
if((s[i]-'0')&&!((s[i]-'0')%3))
flag1=0;
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>k;
sum0=0,E1=0,E2=0,sum_all=0;
memset(sum,0,sizeof(sum));
scanf("%s",s);
cnt();
if(n-k<2)
printf(sum[0]?"yes":"no");
else
{
if(!k)
printf(sum_all%3?"no":"yes");
else
printf(judge()?"yes":"no");
}
putchar(10);
}
}