数位DP
P2657 [SCOI2009] windy 数
题目描述
输入格式
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
最后更新于