TO 3
题目来源:AtCoder Beginner Contest 182 —— C - To 3
中国石油大学icpc 2021个人训练赛第七场
题面:Given is a positive integer N, where none of the digits is 0.Let k be the number of digits in N. We want to make a multiple of 3 by erasing at least 0 and at most k−1 digits from N and concatenating the remaining digits without changing the order.
Determine whether it is possible to make a multiple of 3 in this way. If it is possible, find the minimum number of digits that must be erased to make such a number.
Constraints
1≤N<1018
None of the digits in N is 0.
INPUT
Input is given from Standard Input in the following format:
N
OUTPUT
If it is impossible to make a multiple of 3, print -1; otherwise, print the minimum number of digits that must be erased to make such a number.
题目大意
输入一个在范围1到1e18内的整数,设k为这个数字的位数,最少删除0位,最多删除k-1位,删除数字之后,其余数字直接相连,问最少删除几位,可以使该整数被3整除
///////////////////
这个题是一个数论的题,虽然过的人很多,但是我一时半会儿真的没想明白!
题目分析点
1.因为这个题是需要对于每一位进行操作,所以用字符串来输入可能会更方便一点,所以我选择用字符串将整数读进去。
2.字符出输入之后,我们先把判断一下该字符串能否被3整除,在这里,判断字符串能否被3整除的比较好的办法就是,看所有数字相加的总和是否可以被3整除即可(思考:被4整除,被6整除。。。的数字又都有什么特别的规律呢?)
3.求出总和之后,如果该数字被3整除,则不需要改任何一个数字,直接输出0即可,如果该数字不能被3整除,则要考虑删减数字,因为我们要求删减的最小次数,所以我们肯定希望删减是一步到位的。我们先求出总和%3得到的余数,只要我们能通过删减数字让这个余数变成0不就可以了吗!
4.余数只会有两种,1和2
{
如果余数是1
则我们删除一个1或者4或者7就可以一步到位
如果余数是2
我们只要删除一个2或者5或者8就可以一步到位
(删除3,6,9是没有任何意义的)
所以说对于一个余数是1的数字,只要其中有1或者4或者7他就可以删除他们直接达到目的,答案是1!。
但是如果余数是1,但是数字中却没有1.4.7
余数是2,数字中却没有2 5 8怎么办?
}
**5**考虑一个数字
22222,
22222%3=1,但是其中却没有1 4 7,不能一步到位。
但是我们可以知道 4=2+2;
此时只需要删除两个2即可达成目的
所以22222的答案是2
由此联想出
4=2+2;
7=5+2;
/////////
2=1+1;
5=1+4;
8=1+7或者4+4;
我们可以用 258来凑出,147.
或者用147来凑出258;
这种凑法,答案只能是0或1或者2;
(因为不可能会有
8=4+1+1+1+1这种离谱的凑法);
6.另外就是要注意删除的数字不能超过
k-1;
///////////
AC代码
#include<bits/stdc++.h>
using namespace std;
int numk[10];
int main()
{
string s;
cin>>s;
int sum=0;
for(int i=0;i<s.size();i++)
{
int h=s[i]-'0';
sum+=h;
}
for(int k=0;k<s.size();k++)
{
numk[s[k]-'0']++;
}
if(sum%3==0)
{
printf("0");
}
else
{
int haha=sum%3;
int flag=0;
int ans;
if(haha==1)
{
if(numk[1]!=0||numk[4]!=0||numk[7]!=0)
{
flag=1;
ans=1;
}
if(flag==0)
{
if(numk[2]>=2||(numk[2]>=1&&numk[5]>=1))
{
flag=1;
ans=2;
}
}
}
else if(haha==2)
{
if(numk[2]!=0||numk[5]!=0||numk[8]!=0)
{
flag=1;
ans=1;
}
if(flag==0)
{
if(numk[1]>=2||(numk[1]>=1&&numk[4]>=1)||(numk[1]>=1&&numk[7]>=1)||numk[4]>=2)
{
flag=1;
ans=2;
}
}
}
if(flag==1&&(ans!=s.size()))
{
printf("%d",ans);
}
else
{
printf("-1");
}
}
return 0;
}
我也在网上看了一些关于这个题的题解,写的都比我简洁的多,我这个确实有点麻烦,希望我细心的讲解大家可以看的懂。
//////
遇到瓶颈是人生的常态
夫列子御风而行,泠然善也,旬有五日而后反。彼于致福者,未数数然也。此虽免乎行,犹有所待者也。若夫乘天地之正,而御六气之辩,以游无穷者,彼且恶乎待哉?故曰:至人无己,神人无功,圣人无名。