今天佛了,魔鬼周一,在线教学,有点小累,但还好,今天AC了一道,每日一道,还好达成目标,还以为今天完不成了,最近任务越来越多,如何高效完成该好好思考一下了~最重要的还是学业的复习和预习。

今日兴趣新闻:

《流浪地球》中的逃生气囊球和马斯克有什么关系?

链接:https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_8599496962815210358%22%7D&n_type=0&p_from=1

------------------------------------------------题目----------------------------------------------------------

Polycarp and Div 3

Polycarp likes numbers that are divisible by 3.

He has a huge number ss. Polycarp wants to cut from it the maximum number of numbers that are divisible by 33. To do this, he makes an arbitrary number of vertical cuts between pairs of adjacent digits. As a result, after mm such cuts, there will be m+1m+1 parts in total. Polycarp analyzes each of the obtained numbers and finds the number of those that are divisible by 33.

For example, if the original number is s=3121s=3121, then Polycarp can cut it into three parts with two cuts: 3|1|213|1|21. As a result, he will get two numbers that are divisible by 33.

Polycarp can make an arbitrary number of vertical cuts, where each cut is made between a pair of adjacent digits. The resulting numbers cannot contain extra leading zeroes (that is, the number can begin with 0 if and only if this number is exactly one character '0'). For example, 007, 01 and 00099 are not valid numbers, but 90, 0 and 10001 are valid.

What is the maximum number of numbers divisible by 33 that Polycarp can obtain?

Input

The first line of the input contains a positive integer ss. The number of digits of the number ss is between 11 and 2⋅1052⋅105, inclusive. The first (leftmost) digit is not equal to 0.

Output

Print the maximum number of numbers divisible by 33 that Polycarp can get by making vertical cuts in the given number ss.

Examples

input


output

 

input

 

output

 

input


output


input


output

 

Note

In the first example, an example set of optimal cuts on the number is 3|1|21.

In the second example, you do not need to make any cuts. The specified number 6 forms one number that is divisible by 33.

In the third example, cuts must be made between each pair of digits. As a result, Polycarp gets one digit 1 and 3333 digits 0. Each of the 3333digits 0 forms a number that is divisible by 33.

In the fourth example, an example set of optimal cuts is 2|0|1|9|201|81. The numbers 00, 99, 201201 and 8181 are divisible by 33.

------------------------------------------------题目----------------------------------------------------------

(一) 原题大意:

  输入一个数,某人可以进行以下的操作:  

  某人可以进行任意数量的垂直切割,其中每个切割在一对相邻的数字之间进行。结果数字不能包含额外的前导零(也就是说,当且仅当此数字恰好是一个字符' 0 '时,数字才能以0开头)。例如,007,01和00099不是有效的数字,但90,0和10001是有效的。

  分割出来的每一部分的数,都能被3整除,则说明可以得到一个整除3的数,其中0也能被3整除,请算一算能为该同学获得最多几个整除3的数呢?

(二) 题目分析:

  首先,肯定是需要得到每一个数字,如果这个数字是0,那么答案比较简单,如果当前数字能够直接被3整除(0, 3, 6, 9)的话,那就直接结果加一就好了。

  然后如果这两种情况都不成立,那么就是两位数以上的组合了,在这里我出了点弯路子,刚开始用求和法,然后却疯狂到test11就WA了,检查了很久也没有找到解决办法,后来心理课结束后和大佬们交谈才发现一些新想法奥秘,那就是符合3整除的数,求余之后有特殊关系,待会列一下我的弯路给自己提个醒。

  然后我换了一种方法,那就是用加和,利用整除3的特性,下面也列出来了,但还是WA了。

  最后我翻看一些博客,发现在我原来写得基础上,只要改变if条件的位置就能AC了,总结来说有三种情况:当前数字模3为0、现有的数字之和模3为0(当前正在处理的)、隔了三个数字了一定可以做到模3为0

(三) 错误弯路:

  第一次直接用long long int 去扔输入,然后丢OJ结果发现第一次就WA了

#include<stdio.h>
#include<math.h>
long long int temp,num;
int temp_num,counter,ans,k;
int main()
{
ans = ;
scanf("%d",&temp);
num = temp;
while(num>)
{
k = num % ;
if(k == )
{
ans++;
counter = temp_num = ;
num = num / ;
continue;
}
if(k % == )
{
ans++;
counter = temp_num = ;
}
else
{
temp_num += k * pow(,counter);
if(temp_num % == )
{
ans++;
counter = temp_num = ;
}
}
num = num / ;
}
printf("%d\n",ans);
return ;
}

  结果是因为scanf这里用了%d,结果才发现过样例1000000000000000000000000000的时候错了,然后就换了一种方法,像这样大数都只能用char来处理了:

  第二步弯路,然后就改了改,扔进去:

#include<stdio.h>
#include<math.h>
#include<string.h>
char input[];
int num;
int temp_num,counter,ans,k;
int main()
{
ans = ;
scanf("%s",&input);
for(int i = strlen(input) - ;i>=;i--)
{
k = input[i];
if(k == )
{
ans++;
counter = temp_num = ;
continue;
}
if(k % == )
{
ans++;
counter = temp_num = ;
}
else
{
temp_num += k * pow(,counter);
if(temp_num % == )
{
ans++;
counter = temp_num = ;
}
}
}
printf("%d\n",ans);
return ;
}

  到这里样例就都全过了,代码思路是:将输入的值扔进char数组里,然后获取到他的长度,从后往前来处理,从判断当前数是否为0,如果是的话就直接加一,然后判断当前数能否被3整除,如果可以就也直接加一。都没有的话,就存到一个temp变量里,然后与后面处理的数求和,然后判断该求和temp是否能被3整除。结果这里到test11就WA了,半天没搞懂,后来和同学讨论了半天,结果发现对于122 221这样的数判断就出现了问题,后来实在解不了,嫌判断太乱,都单独列了出来,结果居然AC了:

#include<stdio.h>
#include<math.h>
#include<string.h>
char input[];
long long int temp_num,counter,ans,k;
int main()
{
ans = counter = ;
scanf("%s",&input);
for(int i = strlen(input) - ;i>=;i--)
{
k = input[i] - '';
temp_num += k;
counter++;
if(counter == )
{
ans++;
counter = temp_num = ;
continue;
}
else if(k % == )
{
ans++;
counter = temp_num = ;
continue;
}
else if(temp_num % == )
{
ans++;
counter = temp_num = ;
continue;
}
}
printf("%d\n",ans);
return ;
}

  结果误打误撞发现了一些牛皮的数学思维~ 待会献上:

(四)AC代码:

    因为代码比较简单,依旧不分块了~

#include<stdio.h>
#include<math.h>
#include<string.h>
char input[];
long long int temp_num,counter,ans,k;
int main()
{
ans = counter = ;
scanf("%s",&input);
for(int i = strlen(input) - ;i>=;i--)
{
k = input[i] - '';
temp_num += k;
counter++;
if(counter == || k % == || temp_num % == )
{
ans++;
counter = temp_num = ;
}
}
printf("%d\n",ans);
return ;
}

(五)AC截图:

(六)解后分析:

    分析1 - 能被特殊数整除的特征

1、能被2整除的数的特征。

如果一个数能被2整除,那么这个数末尾上的数为偶数,“0”、“2”、“4”、“6”、“8”。

2、能被3整除的数的特征。

   如果一个数能被3整除,那么这个数所有数位上数字的和是3的倍数。例如:225能被3整除,因为2+2+5=9,9是3的倍数,所以225能被3整除。

3、能被4整除的数的特征。

   如果一个数的末尾两位能被4整除,这个数就能被4整除。例如:15692512能不能被4整除呢?因为15692512的末尾两位12,能被4整除,所以15692512能被4整除。

4、能被5整除的数的特征。

   若一个数的末尾是0或5,则这个数能被5整除。

5、被7整除的数的特征。

方法一:若一个整数的个位数字截去,再从余下的数中,减去个位数的2倍,如果差是7的倍数,则原数能被7整除。如果差太大或心算不易看出是否是7的倍数,就需要继续上述「截尾、倍大、相减、验差」的过程,直到能清楚判断为止。例如,判断133是否是7的倍数的过程如下:13-3×2=7,所以133是7的倍数;又例如判断6139是否7的倍数的过程如下:613-9×2=595 , 59-5×2=49,所以6139是7的倍数,以此类推。

方法二:如果一个多位数的末三位数与末三位以前的数字所组成的数的差,是7的倍数,那么这个数就能被7整除。例如:280678末三位数是678,末三位以前数字所组成的数是280,679-280=399,399能被7整除,因此280679也能被7整除。

方法三:首位缩小法,减少7的倍数。

例如,判断452669能不能被7整除,452669-420000=32669,只要32669能被7整除即可。可对32669继续,32669-28000=4669,4669-4200=469,469-420=49,49当然被7整除所以452669能被7整除。
6、能被8整除的数的特征。
   若一个整数的未尾三位数能被8整除,则这个数能被8整除。
7、能被9整除的数的特征。
   若一个数的数位上的数字的和能被9整除,则这个整数能被9整除。例如:111111111能不能被9整除呢?因为1+1+1+1+1+1+1+1+1=9,9是9的倍数,所以111111111能被9整除。
8、能被11整除的数的特征。
   方法一:若一个整数的奇位数字之和与偶位数字之和(从右往左数)的差能被11整除,则这个数能被11整除。例如,判断491678能不能被11整除。奇位数字之和8+6+9=23;偶位数字之和7+1+4=12;23-12=11,11能被11整除,所以491678能被11整除。这种方法叫作“奇偶位差法”。

方法二:11的倍数检验法也可用上述检查7的「割尾法」处理!过程唯一不同的是:倍数不是2而是1!例如:判断491678能不能被11整除,49167-8=49159,4915-9=4906,

490-6=484,48-4=44。44能被11整除,所以得491678能被11整除。

方法三:还可以根据7的方法二判断。例如:283679的末三位数是679,末三位以前数所组成的数是283,679-283=396,396能被11整除,因此283679就一定能被11整除。
9、能被13整除的数的特征。
   方法一:若一个整数的个位数字截去,再从余下的数中,加上个位数的4倍,如果和是13的倍数,则原数能被13整除。如果和太大或心算不易看出是否13的倍数,就需要继续上述「截尾、倍大、相加、验和」的过程,直到能清楚判断为止。

例如,判断1284322能不能被13整除。128432+2×4=128440,12844+0×4=12844,

1284+4×4=1300,1300÷13=100。所以1284322能被13整除。

方法二:前面7的方法二,也适用判定13。例如:判定1284322能不能被13整除,128432的末尾三位数是322,末尾以前的数字所组成的数是1284,322-1284=-962。962÷13=74。所以1284322能被13整除。
10、能被17整除的数的特征。
    方法一:若一个整数的个位数字截去,再从余下的数中,减去个位数的5倍,如果差是17的倍数,则原数能被17整除。如果差太大或心算不易看出是否17的倍数,就需要继续上述「截尾、倍大、相减、验差」的过程,直到能清楚判断为止。例如,判断1675282能不能被17整除,167528-2×5=167518,16751-8×5=16711,1671-1×5=1666,166-6×5=136,

136÷17=8,所以1675282能被17整除。

方法二:若一个整数的末三位与3倍的前面的隔出数的差能被17整除,则这个数能被17整除。例如,判断1675282能不能被17整除,1675282的末三位是282,前面的数是1675,

282-1675×3=-4743,4743÷17=279,所以1675282能被17整除。

11、能被19整除的数的特征。  

方法一:若一个整数的末三位与7倍的前面的隔出数的差能被19整除,则这个数能被19整除。例如,判断234555能不能被19整除,234555末尾三位数是555,前面三位是234,

555-234×7=-1083,1083÷19=57,所以234555能被19整除。

方法二:若一个整数的个位数字截去,再从余下的数中,加上个位数的2倍,如果和是19的倍数,则原数能被19整除。如果和太大或心算不易看出是否19的倍数,就需要继续上述「截尾、倍大、相加、验和」的过程,直到能清楚判断为止。
12、能被23整除的数的特征。
    若一个整数的末四位与前面5倍的隔出数的差能被23(或29)整除,则这个数能被23整除。

13、能被25整除的数的特征。

如果一个数的末尾两位能被25整除,则这个数能被25整除。

14、能被125整除的数的特征。

如果一个数的末尾三位能被125整除,则这个数能被125整除。

分析2-为什么将counter == 3判断单独拿出来就能求解了?

  考虑将每个数字模3以后的结果。

  如果对于当前数字能被3整除(0、3、6、9)模3结果为0的数,则直接个数加1

  如果是两个数字那就有四种可能(1,1) (2, 2) (1, 2) (2, 1)其中后两个组合之和为3能被3整除

  如果是三个数字对于之前两个数字的组合只剩下(1, 1)和(2, 2) 那么下个数不管是1还是2都可以组成一个3的整数倍

分析3-其他优质解法搜集:

  解法一:

    贪心思路:
  对每位数字对3求余,则结果只能是0、1、2.如果当前位是0,则对结果贡献为1,如果不为0,则判断连续出现2或者1的数目num,如果num%3为0,则对结果的贡献为num/3,否则可以找到一个与当前数字不相等的数字(前面连续出现的是2,当前为1。或者前面连续出现的是1,当前为2),则对结果贡献是num/3+1.

#include<bits/stdc++.h>

using namespace std;
string s; int main() {
ios::sync_with_stdio(false), cin.tie();
cin >> s;
for(int i = ; i < s.length(); i++) {
s[i] = (s[i] - '') % + '';
}
int num = ;
int ans = ;
for(int i = ; i < s.length(); i++) {
if(s[i] == s[i-]) num++;
else {
if(s[i] == '') {
ans += num / ;
num = ;
}
else if(s[i-] == '') {
ans += num;
num = ;
}
else {
ans += num / ;
if(num % ) {
ans++;
num = ;
}
else num = ;
}
}
}
if(s[s.length()-] == '') ans += num;
else ans += num / ;
cout << ans << endl;
return ;
}

  解法二:

  dp思路:
  dp[i]表示截止到下标为i的元素之前最多有多少个片段%3=0。很容易想到当(sum[i]-sum[j]) % 3 == 0时,dp[i] = max{dp[j]} + 1;所以用一个pre[]数组表示和当前sum值相等的上一个sum值,中间肯定经历了一个(+3)%3的过程。所以最终的状态方程是dp[i] = max(dp[pre[sum]]+1, dp[i]);

#include<bits/stdc++.h>

using namespace std;
const int maxn = 1e7;
string s;
int dp[maxn], pre[maxn]; int main() {
ios::sync_with_stdio(false), cin.tie();
memset(pre, -, sizeof(pre));
cin >> s;
for(int i = ; i < s.length(); i++) {
s[i] = (s[i] - '') % + '';
}
dp[] = (s[] == '');
int sum = s[] - '';
pre[sum] = ;
for(int i = ; i < s.length(); i++) {
int t = s[i] - '';
sum = (sum + t) % ;
dp[i] = dp[i-];
if(sum == ) dp[i] = max(dp[i], );
if(pre[sum] != -) dp[i] = max(dp[pre[sum]] + , dp[i]);
pre[sum] = i;
}
cout << dp[s.length()-] << endl;
return ;
}

  解法三:大师兄的神奇循环解法:

注:如果有更好的解法,真心希望您能够评论留言贴上您的代码呢~互相帮助互相鼓励才能成长鸭~~

『ACM C++』 Codeforces | 1005D - Polycarp and Div 3的更多相关文章

  1. 『ACM C++』 Codeforces | 1066A - Points in Segments

    大一生活真 特么 ”丰富多彩“ ,多彩到我要忙到哭泣,身为班长,很多班级的事情需要管理,也是,什么东西都得体验学一学,从学生会主席.团委团总支.社团社长都体验过一番了,现在差个班长也没试过,就来体验了 ...

  2. 『ACM C++』 Codeforces | 1003C - Intense Heat

    今日兴趣新闻: NASA 研制最强推进器,加速度可达每秒 40 公里,飞火星全靠它 链接:https://mbd.baidu.com/newspage/data/landingsuper?contex ...

  3. 『ACM C++』 Codeforces | 1066B - Heaters

    今日不写日感,直接扔上今日兴趣点: 新研究称火星曾经有一个巨大的地下水系统 链接:https://mbd.baidu.com/newspage/data/landingsuper?context=%7 ...

  4. CodeForces 1005D Polycarp and Div 3(思维、贪心、dp)

    http://codeforces.com/problemset/problem/1005/D  题意: 给一个仅包含数字的字符串,将字符串分割成多个片段(无前导0),求这些片段里最多有多少是3的倍数 ...

  5. 『ACM C++』 PTA 天梯赛练习集L1 | 007-011

    真的是忙头晕了,学业.ACM打题.班级活动.自学新东西,哇这充实的大学~ ------------------------------------------------L1-007--------- ...

  6. 『ACM C++』HDU杭电OJ | 1418 - 抱歉 (拓扑学:多面体欧拉定理引申)

    呕,大一下学期的第一周结束啦,一周过的挺快也挺多出乎意料的事情的~ 随之而来各种各样的任务也来了,嘛毕竟是大学嘛,有点上进心的人多多少少都会接到不少任务的,忙也正常啦~端正心态 开心面对就好啦~ 今天 ...

  7. 『ACM C++』HDU杭电OJ | 1425 - sort (排序函数的特殊应用)

    今天真的是累哭了,周一课从早八点半一直上到晚九点半,整个人要虚脱的感觉,因为时间不太够鸭所以就回头看看找了一些比较有知识点的题来总结总结分析一下,明天有空了就开始继续打题,嘻嘻嘻. 今日兴趣电影: & ...

  8. 『ACM C++』HDU杭电OJ | 1415 - Jugs (灌水定理引申)

    今天总算开学了,当了班长就是麻烦,明明自己没买书却要带着一波人去领书,那能怎么办呢,只能说我善人心肠哈哈哈,不过我脑子里突然浮起一个念头,大二还要不要继续当这个班委呢,既然已经体验过就可以适当放下了吧 ...

  9. 『ACM C++』Virtual Judge | 两道基础题 - The Architect Omar && Malek and Summer Semester

    这几天一直在宿舍跑PY模型,学校的ACM寒假集训我也没去成,来学校的时候已经18号了,突然加进去也就上一天然后排位赛了,没学什么就去打怕是要被虐成渣,今天开学前一天,看到最后有一场大的排位赛,就上去试 ...

随机推荐

  1. 批量删除微博的js代码

    清空微博,网上找了一段js代码,试了下,还行. var fileref=document.createElement('script') fileref.setAttribute("type ...

  2. SpringMVC学习(五)——拦截器示例

    部分内容摘自开涛的<跟我学SpringMVC.PDF> 拦截器,本质类似于AOP,主要的应用场景: 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV等. 2.权限检查 ...

  3. SQL Server ->> OFFSET & FETCH子句

    SQL Server 2012引入OFFSET + FETCH字句.它俩出现在SELECT .... ORDER BY ...后面.作用是告诉SQL Server在结果集中忽略前N行然后取前M行出来. ...

  4. Oracle案例01——ORA-09925: Unable to create audit trail file

    2018年春节后第一天上班就遇到一个审计日志无法写入的问题,具体解决思路如下. 一.错误日志 数据库错误日志内容: Fri Feb 23 11:16:30 2018OS Audit file coul ...

  5. win10下Java环境配置

    JAVA_HOME : E:\ensoft\jdk(这个是jdk安装路径) CLASSPATH : .;E:\ensoft\jdk\lib;E:\ensoft\jdk\lib\dt.jar;E:\en ...

  6. 使用qt的hostInfo类,查看本机的IP和设备

    创建NetWorkInformation类,main.cpp直接生成. #include "networkinformation.h" #include <QApplicat ...

  7. 第一周 day1 Python学习笔记

    为什么要学习Python? Python擅长的领域 1. python2.x中不支持中文编码,默认编码格式为ASCII码,而python3.x中支持Unicode编码,支持中文,变量名可以为中文,如: ...

  8. TP5:隐藏inde.php文件

    原文地址:https://www.cnblogs.com/wangjiayi/p/7943268.html 一,找到/public/.htaccess文件,如果你的入口文件已经移动到根目录下,那么你的 ...

  9. ASN.1详解

    Chapter 4 ASN.1 4.1 网络数据表示及编码4.2 ASN.1的基本概念4.3 基本编码规则 4.1 网络数据表示及编码ASN.1(Abstract Syntax Notation 1) ...

  10. 随机以及时间相关函数——C语言描述

    随机相关的函数 头文件 stdlib.h 相关函数 :rand .srand rand( rand C++ Reference ) 函数声明:int rand( void ); rand函数返回一个位 ...