列表

详情


NC13590. 永远的零

描述

相信大家都玩过给一串数字中间填上加减乘除符号使其算出给定值的游戏吧。
例如给定一串数字5555,在中间填一个加号后就可以得到110,即:55+55=110.
在本问题中,wmq想知道在中间某个位置添加一个加号后,算出来的和的后面最多有多少个0。
注意:添加完加号后,如果某个加数最高位开始有若干位为0,则忽略这些0。

输入描述

多组输入,每行为一串数,每个数字在0到9之间。保证这串数的第一个数字非0。数字个数n满足2≤n≤10^6。 所有输入数字个数不超过4×10^6。

输出描述

对每组数据输出一行,即算出来的数后面最多有多少个0。

示例1

输入:

2017
2018

输出:

0
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 50ms, 内存消耗: 13844K, 提交时间: 2023-04-17 13:05:37

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1000002
char s[MAXN],str[MAXN];
int fail[MAXN];
int num9[MAXN];
int len,zero;
void make_fail()
{
    for(int i=1,j=0;s[i];i++)
    {
        while(j&&s[i]!=s[j]) j=fail[j-1];
        if(s[i]==s[j]) fail[i]=++j;
        else fail[i]=0;
    }
}
int search(char *str)
{
    int ans=0;
    for(int i=len,j=0;i>=0;i--)
    num9[i]=str[i]=='9'?++j:j=0;
    for(int i=1,j=0;i<=len;i++)
    {
        for(;j&&str[i]!=s[j];j=fail[j-1])
        {
            if(i-j>j) ans=max(ans,i==len?min(j+num9[j],i-j):j);
            else if(j>=zero) ans=max(ans,i-j+num9[2*(i-j)]);
        }
        if(str[i]==s[j]) j++;
    }
    return max(ans,zero-1);
}
int main()
{
    while(scanf("%s",str)==1)
    {
        len=strlen(str);
        reverse(str,str+len);
        for(zero=0;str[zero]=='0';s[zero++]='0');
        s[zero]='9'+'1'-str[zero];
        for(int i=zero+1;i<len;i++)
        s[i]='9'+'0'-str[i];
        s[len]=0;
        make_fail();
        printf("%d\n",search(str));
    }
    return 0;
}

C++14(g++5.4) 解法, 执行用时: 55ms, 内存消耗: 9972K, 提交时间: 2020-04-15 21:22:45

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1000002
char s[MAXN],str[MAXN];
int fail[MAXN];
int num9[MAXN];
int len,zero;
void il(){
    for(int i=1,j=0;s[i];i++){
        while(j&&s[i]!=s[j]) j=fail[j-1];
        if(s[i]==s[j]) fail[i]=++j;
        else fail[i]=0;
    }
}
int search(char *str){
    int ans=0;
    for(int i=len,j=0;i>=0;i--)
    num9[i]=str[i]=='9'?++j:j=0;
    for(int i=1,j=0;i<=len;i++){
        for(;j&&str[i]!=s[j];j=fail[j-1]){
            if(i-j>j) ans=max(ans,i==len?min(j+num9[j],i-j):j);
            else if(j>=zero) ans=max(ans,i-j+num9[2*(i-j)]);
        }
        if(str[i]==s[j]) j++;
    }
    return max(ans,zero-1);
}
int main(){
    while(scanf("%s",str)==1){
        len=strlen(str);
        reverse(str,str+len);
        for(zero=0;str[zero]=='0';s[zero++]='0');
        s[zero]='9'+'1'-str[zero];
        for(int i=zero+1;i<len;i++)
        s[i]='9'+'0'-str[i];
        s[len]=0;
        il();
        printf("%d\n",search(str));
    }
}

C++11(clang++ 3.9) 解法, 执行用时: 62ms, 内存消耗: 13900K, 提交时间: 2020-03-10 11:12:46

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1000002
char s[MAXN],str[MAXN];
int fail[MAXN];
int num9[MAXN];
int len,zero;
void make_fail()
{
	for(int i=1,j=0;s[i];i++)
	{
		while(j&&s[i]!=s[j]) j=fail[j-1];
		if(s[i]==s[j]) fail[i]=++j;
		else fail[i]=0;
	}
}
int search(char *str)
{
	int ans=0;
	for(int i=len,j=0;i>=0;i--)
	num9[i]=str[i]=='9'?++j:j=0;
	for(int i=1,j=0;i<=len;i++)
	{
		for(;j&&str[i]!=s[j];j=fail[j-1])
		{
			if(i-j>j) ans=max(ans,i==len?min(j+num9[j],i-j):j);
			else if(j>=zero) ans=max(ans,i-j+num9[2*(i-j)]);
		}
		if(str[i]==s[j]) j++;
	}
	return max(ans,zero-1);
}
int main()
{
	while(scanf("%s",str)==1)
	{
		len=strlen(str);
		reverse(str,str+len);
		for(zero=0;str[zero]=='0';s[zero++]='0');
		s[zero]='9'+'1'-str[zero];
		for(int i=zero+1;i<len;i++)
		s[i]='9'+'0'-str[i];
		s[len]=0;
		make_fail();
		printf("%d\n",search(str));
	}
	return 0;
}

上一题