题解:HDU 7441

Link

1. Description

给定一个长度为 \(k\) 的关系串 \(R\),称一个长度为 \(k+1\) 的非负整数序列满足 \(R\) 的限制,表示对于 \(1\le i\le k\),都有 \(\begin{cases}a_i<a_{i+1}\ (R_i='<')\\a_i>a_{i+1}\ (R_i='>')\end{cases}\)

我们规定一个非负整数 \(n\) 可以按照数位写为一个整数序列,例如 \(123\) 可以写为 \(1\ 2\ 3\),特殊的 \(0\) 可以写为 \(0\),现在给定 \(l,r\) 和一个关系串 \(R\),询问 \(\sum_{i=l}^r f(i,R)\),其中 \(f(i,R)\) 表示将 \(i\) 写为整数序列后,满足 \(R\) 的限制的子序列数量。

2. Solution

显然,这个巨大的数字让我们不能真的枚举 \(i\),然后求解,但是这个数据范围,显然可以使用数位 DP,我们不妨设计状态 \(p,q,pre,lead,limit\),分别表示现在已经定了前 \(p\) 位,选出的子序列已经匹配了 \(q\) 为关系串,子序列的上一位为 \(pre\),有/没有前导零,是/不是上限。

转移的话,只需要枚举这一位放什么数字,是否选入子序列即可。

需要注意的是,这个时候需要把 \(limit\) 也计入记忆化的范畴,因为基本的数位 DP 时,每一个上限只会遍历一次,而这个时候却会遍历不只一次。

3. Code

/*by qwer6*/
/*略去缺省源和快读快写*/
const int N=505,mod=998244353;
int n,m,T;
int a[N],f[N][N][10][2][2],vis[N][N][10][2][2];
char l[N],r[N],R[N];
int mul(int x,int y){
	long long res=1ll*x*y;
	return res>=mod?res%mod:res;
}
int add(int x,int y){
	x+=y;
	return x>=mod?x-mod:x;
}
int sub(int x,int y){
	x-=y;
	return x<0?x+mod:x;
}
int dfs(int p,int q,int pre,bool lead,bool limit,bool mark){
	if(p==n+1){
		if(lead)return 0;
		if(q<=m)return 0;
		return 1;
	}
	if(vis[p][q][pre][lead][limit]==T)return f[p][q][pre][lead][limit];
	int res=0;
	for(int i=limit?a[p]:9;i>=0;i--){
		res=add(res,dfs(p+1,q,pre,lead&i==0,limit&i==a[p],mark));
		if(q<=m&&(lead==0||i>=1)){
			if(q==0)res=add(res,dfs(p+1,1,i,0,limit&i==a[p],mark));
			else{
				if(R[q]=='>'&&pre>i)res=add(res,dfs(p+1,q+1,i,0,limit&i==a[p],mark));
				if(R[q]=='<'&&pre<i)res=add(res,dfs(p+1,q+1,i,0,limit&i==a[p],mark));
			}
		}
	}
	vis[p][q][pre][lead][limit]=T;
	f[p][q][pre][lead][limit]=res;
	return res;
}
int solve(char *c,bool flag,bool mark){
	T++;
	n=strlen(c+1);
	for(int i=1;i<=n;i++)a[i]=c[i]^'0';
	if(flag){
		a[n]--;
		for(int i=n;i>1;i--){
			if(a[i]<0){
				a[i]+=10;
				a[i-1]--;
			}else break;
		} 
		if(a[1]<=0){
			n--;
			for(int i=1;i<=n;i++)a[i]=a[i+1];
		}
	}
	return dfs(1,0,0,1,1,mark);
}
signed main(){
	int t;
	read(t);
	while(t--){
		scanf("%s%s%s",l+1,r+1,R+1);
		m=strlen(R+1);
		write(sub(solve(r,0,0),solve(l,1,1))),Nxt;
	}
}
posted @ 2025-04-17 20:41  陈牧九  阅读(9)  评论(0)    收藏  举报