【牛客练习赛50】tokitsukaze and Segmentation

题目描述

tokitsukaze有一个长度为 n n n的字符串,字符串仅包含 0 9 '0'-'9' 09
tokitsukaze要把这个字符串切割成若干个子串,每个子串作为一个十进制的数,能被3整除,且不含前导0。
问有多少种切割的方案。由于答案可能很大,请输出mod 998244353 998244353 998244353 后的结果。

输入描述:

第一行包含一个正整数 n n n,( 1 n 1 0 5 1≤n≤10^5 1n105)。
第二行包含一个长度为 n n n的字符串 s s s,( 0 s [ i ] 9 '0'≤s[i]≤'9' 0s[i]9)。

输出描述:

输出一个整数,表示方案数,mod 998244353 998244353 998244353 后的结果。

示例1

输入

1
1

输出

0

示例2

输入

1
0

输出

1

示例3

输入

4
1203

输出

3

说明
(1) 1203
(2) 120|3
(3) 12|0|3
所以方案数为3。
注意:12|03,视作不合法,因为有前导0。

Solution

易知:如果 3 s 3 | s 3s, 3 t 3 | t 3t, 那么 3 s 1 0 x + t 3 | s * 10^x+ t 3s10x+t x x x t t t的位数
所以分段递推。
分成x段,保证每段是3的倍数且最短
用v记录是否为0

for i = 1 to n do
	t = t + a[i]
	tmp = (tmp + a[i] - '0') % 3
	if tmp == 0 //找到了
	    if t == '0' v.push_back(true)
	    else v.push_back(false)
	    t = '0'

特判无解:

if v.empty or tmp != 0
	puts("0");
	exit

初始化 f [ x + 1 ] = 1 f[x + 1] = 1 f[x+1]=1
伪代码:

for i = x downto 1
    if 第i个=0
    	f[i] = f[i + 1]
    else
        f[i] = (f[i + 1] + f[i + 2] + ... f[x + 1]) % Mod

代码如下

#include <cstdio>
#include <vector>
#include <string>

using namespace std;

const long long N = 1e5 + 10, Mod = 998244353;
long long n, tmp = 0, f[N];
char a[N];
string t("");

vector<bool> v;

long long main()
{
	scanf("%lld%s", &n, a + 1);
	for (long long i = 1; i <= n; i++)
	{
		t += a[i];
		tmp = (tmp + a[i] - '0') % 3;
		if (tmp == 0)
		{
			if (t == "0") v.push_back(true);
			else v.push_back(false);
			t = "";
		}
	}
	if (v.empty() || tmp != 0)
	{
		puts("0");
		return 0;
	}
	tmp = 1; f[v.size()] = 1;
	for (long long i = v.size() - 1; i >= 0; i--)
	{
		if (v[i])
			f[i] = f[i + 1];
		else f[i] = tmp;
		tmp = (tmp + f[i]) % Mod;
	}
	printf("%lld\n", f[0]);

	return 0;
}
全部评论

相关推荐

02-24 10:34
门头沟学院 Java
在思考的熊熊很讨厌吃香菜:之前发最美的女孩基本爱答不理,发最帅的hr终于有反馈了,女孩子也要自信起来
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务