【玄 5 关】数位 DP 板子求调
  • 板块题目总版
  • 楼主CuteChat
  • 当前回复3
  • 已保存回复3
  • 发布时间2024/7/19 20:08
  • 上次更新2024/7/19 21:13:45
查看原帖
【玄 5 关】数位 DP 板子求调
726525
CuteChat楼主2024/7/19 20:08

来源:杭州发电大学联赛(1)I 题。


对于一个十进制非负整数 nn,我们可以按照从高位到低位将其写成一个由数位 0∼90∼9 构成的字符串 S(n)S(n)(不含前导 00)。

称一个仅由 <\texttt < 和 >\texttt > 组成的串为关系串。对于一个长度为 kk 的关系串 S=s1s2…sk+1S=s_1s_2\dots s_{k+1},如果任意 1≤i≤k1≤i≤k,都有关系 ??(??,??+1)?_? ( ?_? , ?_{? + 1})成立,则称字符串 SS 满足关系串 RR 的限制。

其中关系 ri(si,si+1)r_i (s_i,s_{i+1}) 成立只有两种情况,r=<r=\texttt< 且 si<si+1s_i< s_{i+1} 或者 r=>r=\texttt> 且 si>si+1s_i >s_{i+1} 比较按照字典序顺序。

现在定义 f(n,R)f(n,R) 表示 S(n)S(n) 中有多少个子序列满足关系串 RR 的限制。给定 l,r,Rl,r,R,求:

其中一个字符串的子序列定义为从原字符串中删去若干个(可以不删或删空)字符得到的新字符串。


本题单个测试点内包含多组测试数据。

第一行一个整数 ?(1≤?≤10)? ( 1 ≤ ? ≤ 10 ) ,表示数据组数。

对于每组数据,第一行两个整数 (1≤?≤?<10500)( 1 ≤ ? ≤ ? < 1 0^{500} ),意义如题。

第二行一个关系串 ?(1≤∣R∣≤500)? (1≤∣R∣≤500),意义如题。

输入:

5
12435 12435
<<
114514 114514
<><
1919810 1919810
<><>
1234 4321
<>
114514 1919810
<>>

输出

7
5
5
4628
4377883

错误代码

#include <bits/stdc++.h>
using namespace std;
#define int long long

int n, m, k, dp[506][506][10][2][2][2];
char l[506], r[506], R[506];
const int p = 998244353;

int dfs(int i, int ri, int lst, int limited, int unlim, int zero) {
	if (i == n + 1) return 1;
	if (dp[i][ri][lst][limited][unlim][zero] != -1) return dp[i][ri][lst][limited][unlim][zero];
	int ans = 0;//dfs(i + 1, ri, lst, limited, unlim, zero);
	//cout << lst << " " << ri << " " << i << " " << " " << limited << " " << unlim << "\n";
	if (ri == 0) {
		assert(!zero);
		for (int dig = (unlim ? 0ll : l[i] - 48); dig <= (limited ? 9 : (int)(r[i] - '0')); ++dig) {
			ans += dfs(i + 1, ri + (zero || (dig != 0)), dig,  (limited || (dig != r[i] - '0')),  (unlim || (dig != l[i] - '0')), zero || (dig != 0));
		}
	} else if (ri <= k && R[ri] == '>') {
		assert(zero);
		for (int dig = (unlim ? 0ll : l[i] - 48); dig <= min({lst - 1, (limited ? 9 : (int)(r[i] - '0'))}); ++dig) {
			ans += dfs(i + 1, ri + 1, dig, (limited || (dig != r[i] - 48)), (unlim || (dig != l[i] - '0')),1);
		}
	} else if (ri <= k && R[ri] == '<') {
		assert(zero);
		for (int dig = max((unlim ? 0ll : l[i] - 48), lst + 1); dig <= (limited ? 9 : (int)(r[i] - '0')); ++dig) {
			ans += dfs(i + 1, ri + 1, dig, (limited || (dig != r[i] - 48)),  (unlim || (dig != l[i] - '0')),1);
		}
	} 
	for (int dig = (unlim ? 0ll : l[i] - 48); dig <= (limited ? 9 : (int)(r[i] - '0')); ++dig) {
		ans += dfs(i + 1, ri, lst, (limited || (dig != r[i] - 48)),  (unlim || (dig != l[i] - '0')), zero);
	}
	return dp[i][ri][lst][limited][unlim][zero] = ans % p;
}

void solve() {
	cin >> (l + 1) >> (r + 1) >> (R + 1);
	n = strlen(l + 1);
	m = strlen(r + 1);
	for (int j = m; j >= (m - n + 1); --j) l[j] = l[j - (m - n)];
	for (int j = 1; j <= m - n; ++j) l[j] = '0';
	k = strlen(R + 1);
	memset(dp, 255, sizeof(dp));
	int tmp = dfs(1, 0, 0, 0, 0, 0);
	cout << tmp << "\n";
}

signed main() {
	//ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int tc; cin >> tc;
	while (tc--) solve();
}

蒟蒻要求不高,只求调过样例,我会不会是题意理解错了。

2024/7/19 20:08
加载中...