【Nowcoder】2020牛客暑期多校训练营(第六场)H-Harmony Pairs | 数位dp

本以为自己刷的数位dp够多了

没想到这种类型的真的没见过

不过没事 学到新知识了!

题目链接:https://ac.nowcoder.com/acm/contest/5671/H

题目大意:

询问在小于n中,有多少对(i,j),使得i的数位和大于j的数位和,但是i

题目思路:

第一反应数位dp .. 肯定数位dp

但是我卡在一个地方了..

如何才能同时满足两个条件呢

然后我就一直在搞 :枚举权值和 分上下两次dp等等..发现去重是个困难的事

比赛结束后,看了一下代码瞬间懂了

我们可以在数位dp时直接把这个大小的限制给加进去

同时枚举两个数进行数位dp 在数位dp的同时对两个数的大小进行限制

这样变成了一个裸的数位dp,看最后数位和是否大于0即可,当然过程中出现负数所以要整体向上移

Code:

ll n,m,p;
ll dp[105][2005];
ll a[105];
ll dfs(int pos,int x,int p,int q){
    if(pos==0){
        return x>S;
    }
    if(dp[pos][x][p][q]!=-1) return dp[pos][x][p][q];
    ll ans = 0;
    for(int i=0;i<=(p?a[pos]:9);i++){///枚举p_q | 保证p>q
        for(int k=0;k<=(q?i:9);k++){
            ans += dfs(pos-1,x+k-i,p&&(i==a[pos]),q&&(k==i));
        }
    }
    return ans;
}
char str[maxn];
int main()
{
    memset(dp,-1,sizeof(dp));
    scanf("%s",str+1);
    int len = strlen(str+1);
    for(int i=1;i<=len;i++)
        a[len-i+1] = str[i] - '0';
    printf("%lld\n",dfs(len,S,1,1));
    return 0;
}
/***
***/

Get到了,真的Get到了

你可能感兴趣的:(数位DP)