2020牛客多校第六場H-Harmony Pairs
阿新 • • 發佈:2020-09-01
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; }