1. 程式人生 > 實用技巧 >2020牛客多校第六場H-Harmony Pairs

2020牛客多校第六場H-Harmony Pairs

https://ac.nowcoder.com/acm/contest/5671/H

題意

\(1 \le A \le B \le N\),滿足\(S(A)>S(B)\)\((A,B)\)個數

s是數碼和

題解

數位dp,設\(f[pos][dif][f1][f2]\)為確定了\(pos-n\)位,差為dif,邊界情況為f1和f2的方案數,暴力列舉A,B下一位轉移即可

數位 DP 的複雜度為 O(進位制數 * 位數 + 進位制數 * 新增狀態數)

它並不像其他的記憶化搜尋一樣,搜尋到最後複雜度會降低到 O(1) 直接返回。

即使最終再也沒有新狀態,其複雜度仍然為 O(進位制數 * 位數)

程式碼

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int p = 1e9 + 7;
int initial = 1050;
int digit[105];
int dp[105][2050][2][2];
int dfs(int pos, int dif, int f1, int f2) {
    if (pos == 0) return dif > initial;
    if (dp[pos][dif][f1][f2] != -1) return dp[pos][dif][f1][f2];
    int sz = f1 ? digit[pos] : 9;
    int ans = 0;
    for (int i = 0; i <= sz; i++) {
        int sz2 = f2 ? i : 9;
        for (int j = 0; j <= sz2; j++) {
            ans = (ans + dfs(pos - 1, dif + j - i, f1 && (i == sz), f2 && (j == sz2))) % p;
        }
    }
    dp[pos][dif][f1][f2] = ans;
    return ans;
}
char s[105];
int calc(char s[]) {
    int len = strlen(s + 1);
    for (int i = 1; i <= len; i++) {
        digit[len - i + 1] = s[i] - '0';
    }
    return dfs(len, initial, 1, 1);
}
int main() {
    memset(dp, -1, sizeof(dp));
    scanf("%s", s + 1);
    printf("%d\n", calc(s));
    return 0;
}