数位DP
数位DP用于处理一些与数位有关的问题,主要是计数问题。
P2657 [SCOI2009] windy 数
题目描述
不含前导零且相邻两个数字之差至少为 22 的正整数被称为 windy 数。windy 想知道,在 a 和 b 之间,包括 a 和 b ,总共有多少个 windy 数?
输入格式
输入只有一行两个整数,分别表示 a 和 b。
int A[10];
int dp[10][100];
///
/// \param pos 当前位置
/// \param last 上一个位置的数的值
/// \param limit 当前位置的数是否可以任取
/// \param lead 当前位置之前全是0
/// \return
int dfs(int pos, int last, bool limit, bool lead) {
if (pos <= 0) return 1; // 搜索终点
if (!limit and last != -3 and dp[pos][last] != -1)
return dp[pos][last];
int ans = 0;
for (int v = 0; v <= (limit ? A[pos] : 9); ++v) {
// 根据是否limit决定循环上界
if (abs(v - last) < 2) // 舍弃不合法解
continue;
if (lead and v == 0)ans += dfs(pos - 1, -3, limit && v == A[pos], true);
// 当前位和前面都是0,后面的数可以任取,last赋为-3
else ans += dfs(pos - 1, v, limit && v == A[pos], false);
}
if (!limit) dp[pos][last] = ans;
return ans;
}
int solve(int x) {
memset(A, 0, sizeof(A));
memset(dp, -1, sizeof(dp));
int pos = 0;
while (x) {
A[++pos] = x % 10;
x /= 10;
}
return dfs(pos, -3, true, true);
}
signed main() {
#ifdef LOCAL
freopen("output.txt", "w", stdout);
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(nullptr);
// cin >> t;
// while (t--) {
// solve();
// }
cin >> n >> m;
print(solve(m) - solve(n - 1));
}更一般的模板:
CF1811E
In Japan, the number 4 reads like death, so Bob decided to build a live sequence. Living sequence a contains all natural numbers that do not contain the digit 4 . a=[1,2,3,5,6,7,8,9,10,11,12,13,15,16,…] .
For example, the number 1235 is part of the sequence a , but the numbers 4321 , 443 are not part of the sequence a .
Bob realized that he does not know how to quickly search for a particular number by the position k in the sequence, so he asks for your help.
For example, if Bob wants to find the number at position k=4 (indexing from 1 ), you need to answer ak=5 .
可以用数位dp+二分解决。
最后更新于
这有帮助吗?