2020牛客暑期多校训练营(第六场)H-Harmony Pairs

题目链接
题目描述
给定一个长度100位的数字,统计有几个数满足 A < B AA<B A A A的位数之和大于 B B B的位数之和。
思路
记忆化搜索,挺暴力的数位dp。
d p [ i ] [ j ] [ k ] [ l ] [ m ] dp[i][j][k][l][m] dp[i][j][k][l][m]表示到第 i i i位数字时, A A A B B B的差值为 j j j,且数字 A A A是否为上限最大值, k = 1 k=1 k=1表示该位数字为 A A A的上限最值, l = 1 l=1 l=1表示该位数字为 B B B的上限最值, m = 1 m=1 m=1表示 B B B高位大于 A A A,也就是说当前状态下 B B B必大于 A A A的状态。
因为要考虑负数的状态,所以初始值为 1000 1000 1000,每一位数字为 9 9 9最多的和也只有 900 900 900.
上述的 i , j , k , l , m i,j,k,l,m i,j,k,l,m也对应 d f s dfs dfs中的 p o s , s u m , l i m a , l i m b , f l a g pos,sum,lima,limb,flag pos,sum,lima,limb,flag
代码

#include
using namespace std;

typedef long long LL;
const int p = 1e9 + 7;
int dp[105][2010][2][2][2];
string str;
int len;

LL dfs(int pos, int sum, bool lima, bool limb, bool flag) {
    if(pos == len) {
        return sum > 1000;
    }
    if(dp[pos][sum][lima][limb][flag] != -1) return dp[pos][sum][lima][limb][flag];
    int a = lima ? str[pos] - '0' : 9;
    int b = limb ? str[pos] - '0' : 9;
    LL res = 0;
    for(int i = 0; i <= a; i++) {
        for(int j = 0; j <= b; j++) {
            if(!flag && i > j) continue;
            res = (res + dfs(pos + 1, sum + i - j, lima && i == a, limb && j == b, flag || j > i)) % p;
        }
    }
    return dp[pos][sum][lima][limb][flag] = res;
}

void solve() {
    memset(dp, -1, sizeof dp);
    cin >> str;
    len = str.size();
    printf("%d\n", dfs(0, 1000, 1, 1, 0));
}

int main() {
//    freopen("in.txt", "r", stdin);
    solve();
    return 0;
}

你可能感兴趣的:(比赛,牛客)