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;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务