H - Harmony Pairs
数位DP
题意
给你一个数
,问你符合以下条件的有序对
有几个:
1、 其中
代表
在十进制下的数位和
2、
思路
数位DP基本操作:
1、先写一个按数位的暴力 DFS (不要使用全局状态变量)
// pos: 当前要处理的位
// digitA: A数字当前位的取值范围 [0, digitA]
// digitB: B数字当前位的取值范围 [0, digitB]
// limitA: A数字的取值范围是否被限制 (数位DP常见思想)
// limitB: B数字的取值范围是否被限制 (数位DP常见思想)
// delta: S(A) - S(B)
int dfs(int pos = 0, int delta = 0, bool limitA = true, bool limitB = true) {
if (pos == s.size()) return delta > 0;
// 保证 0 <= A <= N
int digitA = limitA ? s[pos] - '0' : 9, ans = 0;
// 暴力 DFS A, B 每一位的情况
for (int i = 0; i <= digitA; ++i) {
// 保证 0 <= B <= A <= N
int digitB = limitB ? i : 9;
for (int j = 0; j <= digitB; ++j)
ans = (ans + dfs(pos + 1, delta + j - i, limitA && i == digitA, limitB && j == digitB)) % MOD;
}
return ans;
}2、然后直接记忆化(注意 delta 可能会小于 0)
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7, N = 105, M = 2e3 + 5;
const int offset = 900;
string s;
int dp[N][M][2][2];
int dfs(int pos = 0, int delta = offset, bool limitA = true, bool limitB = true) {
if (pos == s.size()) return delta > offset;
if (~dp[pos][delta][limitA][limitB]) return dp[pos][delta][limitA][limitB];
int digitA = limitA ? s[pos] - '0' : 9, ans = 0;
for (int i = 0; i <= digitA; ++i) {
int digitB = limitB ? i : 9;
for (int j = 0; j <= digitB; ++j)
ans = (ans + dfs(pos + 1, delta + j - i, limitA && i == digitA, limitB && j == digitB)) % MOD;
}
return dp[pos][delta][limitA][limitB] = ans;
}
int main() {
memset(dp, -1, sizeof(dp));
cin >> s;
cout << dfs() << endl;
}
查看1道真题和解析
百度公司氛围 554人发布