TO 3 :AtCoder Beginner Contest 182 —— C - To 3

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整除

///////////////////
这个题是一个数论的题,虽然过的人很多,但是我一时半会儿真的没想明白!

题目分析点
.因为这个题是需要对于每一位进行操作,所以用字符串来输入可能会更方便一点,所以我选择用字符串将整数读进去。
.字符出输入之后,我们先把判断一下该字符串能否被3整除,在这里,判断字符串能否被3整除的比较好的办法就是,看所有数字相加的总和是否可以被3整除即可(思考:被4整除,被6整除。。。的数字又都有什么特别的规律呢?)
.求出总和之后,如果该数字被3整除,则不需要改任何一个数字,直接输出0即可,如果该数字不能被3整除,则要考虑删减数字,因为我们要求删减的最小次数,所以我们肯定希望删减是一步到位的。我们先求出总和%3得到的余数,只要我们能通过删减数字让这个余数变成0不就可以了吗!
.余数只会有两种,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怎么办?

****考虑一个数字
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这种离谱的凑法);

.另外就是要注意删除的数字不能超过
k-1;
///////////
AC代码

#include
using namespace std;
int numk[10];
int main()
{
	string s;
	cin>>s;
	int sum=0;
	for(int i=0;i=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;
}

我也在网上看了一些关于这个题的题解,写的都比我简洁的多,我这个确实有点麻烦,希望我细心的讲解大家可以看的懂。

//////
遇到瓶颈是人生的常态

夫列子御风而行,泠然善也,旬有五日而后反。彼于致福者,未数数然也。此虽免乎行,犹有所待者也。若夫乘天地之正,而御六气之辩,以游无穷者,彼且恶乎待哉?故曰:至人无己,神人无功,圣人无名。

你可能感兴趣的:(日常补题,c++,upc)