列表

详情


NC23997. CSL 学数学

描述

CSL 是个喜欢数学的学生。有一天,他开始研究起一些奇怪的数,他把这些数叫做 B 数。B 数的定义是:这个数十进制字符串(不包括前导零)含有所有给定的 n 个字符串。但是这样的数实在是太多了,CSL 需要你的帮助:给定 l 和 r,你需要求
其中 

输入描述

第一行有三个整数 n, l, r,含义如题目描述中所述。

接下来 n 行,每行一个由数字构成的字符串 s。




输出描述

在一行输出一个整数,表示 l 到 r 之间 B 数的和对 998244353 取模后的余数。

示例1

输入:

2 1 100
1
2

输出:

33

示例2

输入:

2 1 1000
100
000

输出:

1000

原站题解

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

C++11(clang++ 3.9) 解法, 执行用时: 42ms, 内存消耗: 6500K, 提交时间: 2019-03-31 15:22:58

#include<bits/stdc++.h>
using namespace std;const int N=107,mod=998244353;
int a[N][10],nxt[N],n,i,j,m,t,w,val[N],q[N],sz=1,bin[N],top;typedef pair<int,int> pa;pa dp[N][N][33][2];char A[N],B[N],s[N];
void ins(int id){
	int now=1;for(int i=0,c;s[i];++i){
		c=s[i]-'0';if(!a[now][c])a[now][c]=++sz;now=a[now][c];
	}val[now]|=id;
}
void acmach(){
	for(int i=0;i<10;++i)a[0][i]=1;
	t=0;w=1;q[0]=1;
	while(t!=w){
		int x=q[t++];
		for(int i=0;i<10;++i)if(a[x][i]){
			nxt[a[x][i]]=a[nxt[x]][i];val[a[x][i]]|=val[nxt[a[x][i]]];q[w++]=a[x][i];
		}else a[x][i]=a[nxt[x]][i];
	}
}
pa dfs(int x,int cur,int S,int pre,int flag){
	if(x==0){if(S==m)return pa(1,0);else return pa(0,0);}
	if(!flag&&dp[x][cur][S][pre].first!=-1)return dp[x][cur][S][pre];
	int mx=flag?q[x]:9;pa res(0,0),tmp;
	for(int i=0;i<=mx;++i){
		if(i==0&&pre&&x!=1){
			tmp=dfs(x-1,cur,S,pre,flag&&i==mx);
		}
		else tmp=dfs(x-1,a[cur][i],S|val[a[cur][i]],pre&&i==0,flag&&i==mx);
		res.first=(res.first+tmp.first)%mod;
		res.second=(res.second+tmp.second+1LL*tmp.first*i%mod*bin[x-1]%mod)%mod;
	}
	if(!flag)dp[x][cur][S][pre]=res;
	return res;
}
void go(string&s)
{reverse(s.begin(),s.end());while(s.size()>1&&s.back()=='0')s.pop_back();reverse(s.begin(),s.end());}
int check(string s){
	go(s);
	int res=0,cur=1;int ans=0;
	for(int i=0;i<s.size();++i)ans+=1LL*(s[i]-'0')*bin[s.size()-i-1]%mod,ans%=mod,res|=val[a[cur][s[i]-'0']],cur=a[cur][s[i]-'0'];
	return res==m?ans:0;
}
int cal(string s){
	go(s);top=0;
	for(i=s.size()-1;i>=0;--i)q[++top]=s[i]-'0';
	return dfs(top,1,0,1,1).second;
}
int main(){
	memset(dp,-1,sizeof(dp));
	for(bin[0]=1,i=1;i<N;++i)bin[i]=1LL*bin[i-1]*10%mod;
	for(scanf("%d%s%s",&n,A,B),m=(1<<n)-1;n--;)scanf("%s",s),ins(1<<n);acmach();
	printf("%lld\n",((0LL+cal(B)-cal(A)+check(A))%mod+mod)%mod);
}

上一题