检验赛d题题解
链接:https://vjudge.net/contest/418598#problem/D
这个题很容易会想到去分离位数,然后加起来是三的倍数那么这个数就是三的倍数,然后我一开始的想法是把位数分离,把不是三的倍数的位数存到一个数组,然后先删掉一个位数去看剩下的和是不是三的倍数,没有的话ans++,然后去删两个,直到全部删掉ans就是-1,但是这样我觉得会超时(其实是我搜索不太行),然后在我去拿一些数据分离位数然后去想的时候发现,其实不需要把所有的位数存到数组里,因为所有的位数其实都可以看成1,2.为什么呢,因为我们的位数要加起来去余3,就比如a+b+c%3,就是a%3+b%3+c%3,而%3的结果只有1,2,发现了这个·就很简单了,用a[1]去记是%3==1的位数出现的次数,a[2]去记%3==2的位数出现的次数.
然后这么想,如果所有位数%3余数为1,这个1是怎么来的,有两种情况,一种是一个1,或者两个2,如果是两个1余数是2,3个1余数为0,四个1相当于一个1,同理2也是这样,所以总和余数出现了1,只需要删掉一个1,或者两个2,但是这个时候就有特例比如说1,1%3的余数是1按理删掉一个1就可以了,但是用脚想都知道1凑不出3的倍数,所以这种情况特判呗,就是只有一位数这位书为1类数输出-1,同理22也是,当是两位数且是2类数输出-1.
那么余数是2的情况也是类似,有两种情况,一种就是一个2类数,一种就是两个1类,只需要删掉一个2类或者2个一类就可以了,只有一位2类数和两位1类数要特判。
最后删掉一个ans++,删不掉ans=-1然后一开始直接判断是不是3的倍数。
代码:
#include<stdio.h>
#include<stdlib.h>
long long a[3];
int main(){
long long n,sum=0,ans=0,nn,cou=0;
scanf("%lld",&n);
nn=n;
if(n%3==0){
printf("0");
exit(0);
}
while(n){
a[n%10%3]++;
sum+=n%10;
n/=10;
cou++;
}
if(sum%3==1){
if(a[1]>0&&cou>1)ans=1;
else if(a[2]>=2&&cou>2)ans=2;
else ans=-1;
}
else{
if(a[2]>0&&cou>1)ans=1;
else if(a[1]>=2&&cou>2)ans=2;
else ans=-1;
}
printf("%lld",ans);
return 0;
}