WOJ 24. Divide by Six

题目

请以此题面为准
无解时输出-1s而不是WTF
数据可能有前导零
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
A positive integer number n is written on a blackboard. It consists of not more than
10510^5
10
​5
​​ 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
nn
n will find a mogical number such that
nn
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
nn
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
nn
n – a positive integer (
1≤n≤10100000 1\le n \le 10^{100000}
1≤n≤10
​100000
​​ ).
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题,不是很难,但是细节问题很多,比赛的时候瞎搞的,搞了半天没出来,亏我还是队里面写dp的,非常惭愧,比赛的时候一直想着能被6整除的数是一个偶数并且各个数位上的数字相加和mod3等于0,然后写了2个小时,wa了11次,好气呀!!代码上有注释,参考大神解法。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+100;
const int INF = 0x3f3f3f3f;

char s[maxn];
int dp[maxn][10];

int main(){
    while(scanf("%s", s+1) != EOF){
        int len = strlen(s+1);

        for(int i = 0; i <= len; i++)
            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;
        for(int i = 1; i <= len; i++){
            int t = s[i] - '0';

/*这个位置是为了防止前导0,因为如果这个数不被初始化,那么这个数就是负无穷,
但是后一个状态可以根据前一个状态完成加1操作,但是这个负无穷加1任然为负无穷,
所以对最后的结果没有影响*/
            if(t != 0) dp[i][t%6] = 1;  


            //要么当前值不选直接根据前一个值的情况
            for(int j = 0; j < 6; j++)
                dp[i][j] = max(dp[i][j], dp[i-1][j]);
            for(int j = 0; j < 6; j++)  //当前值选取然后根据前一个点算出的6个值
                dp[i][(j*10+t)%6] = max(dp[i][(j*10+t)%6], dp[i-1][j]+1);  //
            ans = max(ans, dp[i][0]);  //注意mod6等于0
        }

        if(ans > 0) printf("%d\n", ans);
        else printf("-1s\n");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值