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;
}
posted @ 2020-09-01 15:41  Artoriax  阅读(177)  评论(0编辑  收藏  举报