woj-Divide by Six (dp)(方法巧妙)
来源:互联网 发布:软件版权相关解释 编辑:程序博客网 时间:2024/05/20 14:24
请以此题面为准
无解时输出-1s
而不是WTF
数据可能有前导零
Input file: standard inputOutput file: standard output Time limit: 1 secondMemory limit: 512 mebibytes
A positive integer number n is written on a blackboard. It consists of not more than 105 digits. You have to transform it into a mogicalnumber by erasing some of the digits, and you want to erase as few digits as possible.
The number is lucky if it consists of at least one digit, doesn't have leading zeroes and is a multiple of 6. For example, 0, 66,66666 are lucky numbers, and 00, 25, 77 are not.
Write a program which for the given n will find a mogical number such that n can be transformed into this number by erasing as few digits as possible. You can erase an arbitraty set of digits. For example, they don't have to go one after another in the number n.
Print the length of your answer after the erasing.
If it's impossible to obtain a lucky number, print -1s
.
Input
The first line of input contains n -- a positive integer ( 1≤n≤10100000 ).
Output
Print one number — the number of your lucky number obtained by erasing as few as possible digits. If there is no answer, print -1s
.
Example
Input 1
0010456
Output 1
4
Input 2
11
Output 2
-1s
这道题可以手动模拟,但是我不会,我学习了大神的dp做法
代码很短,只要想明白了也不是很难
先贴代码再进行分析
#include<stdio.h>#include<iostream>#include<cmath>#include<string.h>using namespace std;const int INF=1e9;char s[100000+10];int dp[100000+10][7];int main(){ scanf("%s",s+1); int len=strlen(s+1); for(int i=0; i<=len; i++)//开一个dp数组,初始化 for(int j=0; j<6; j++) dp[i][j]=-INF; int ans=-INF; for(int i=1; i<=len; i++) if(s[i]=='0')ans=1;//如果数字;里有0,那么输出结果至少为1 for(int i=1; i<=len; i++) { int t=s[i]-'0';//字符串转化为数字 if(t!=0) dp[i][t%6]=1; //将t余上6表示t余上后的剩余值 for(int j=0; j<=5; j++) //如果不取,那么就直接把前面的搬过来 dp[i][j]=max(dp[i-1][j],dp[i][j]); for(int j=0; j<=5; j++) //如果取,那么就在上一次的基础上+1 dp[i][(j*10+t)%6]=max(dp[i-1][j]+1,dp[i][(j*10+t)%6]);//(j*10+t)表示加上前面没余完的数看看能不能余完 ans=max(ans,dp[i][0]); } if(ans>0) printf("%d\n",ans); else printf("-1s\n");}
次动规的核心就是分段取余(方法非常巧妙)
对于一个数我先对它取余,当我后面又加上一位的时候,我用这个数余后的数乘上10再加上后一位数,然后再取余
如果取余为0了,那么这两位数为6的倍数
如96 先用9对6取余,剩下3.,下一次的话3*10+6再次对6取余
为0,说明96是6的倍数
这就是 j*10+t 的含义。
dp【i】【j】里面存的就是长度,是模后剩下j的可选数字的长度
对于每一位,我先把上一次模剩下的存过来,这是第一次dp的意义
第二次dp的意义是我新加入的这个数t如果能使我存下的dp的长度变长,那么就+1
其中dp【i】【0】表示到第i个数字的最大的长度
如果还是不理解那么就手动模拟一下过程
推荐模拟数 242
模拟出过程就会更好理解了
- woj-Divide by Six (dp)(方法巧妙)
- woj~24. Divide by Six(dp)
- woj Divide by Six 数位dp
- woj-Divide by Six
- WOJ 24. Divide by Six
- Divide by Six
- dp处理大数整除6的最大位数Divide by Six
- WOJ 29 Werewolf(树形DP+枚举)
- 17年武汉大学网络赛—Divide by Six
- HDU4301 Divide Chocolate(DP)
- fzu 1912 Divisibility by Thirty-six(数论+枚举)
- WOJ 题目1538 B - Stones II (DP)
- hdu 4301 Divide Chocolate(DP)
- 2017武大校赛网络预选赛C题 Divide by Six
- Hotal (巧妙地dp设计)
- 采用六西格玛(Six Sigma)方法优化业务流程
- WOJ(记忆化搜索)
- woj 1049 dp
- 2017年4月17日面试题
- 【cc2541开发环境】IAR8.20.2安装步骤
- tensorflow实现迁移学习
- Thinkphp3.23下的发送邮件配置
- [COGS 1489]玩纸牌:期望
- woj-Divide by Six (dp)(方法巧妙)
- Mali develop center
- java虚拟机:垃圾回收机制
- Java 序列化Serializable详解(附详细例子)
- UI Automator2.0 : 保存截图和输出log
- 关于指数循环节的证明
- System.arraycopy
- 使用Calendar来获取当前日期和时间
- 【信息安全技术及应用】系统安全防护技术