码迷,mamicode.com
首页 > 其他好文 > 详细

【AHOI 2009】同类分布

时间:2020-03-19 17:49:21      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:状态   memset   include   ++   return   const   type   cstring   size   

\(Solution\)

发现之前代码的样式时常会出现不同颜色很不协调的东东,,,然后,发现原来是代码那一栏没打 cpp。(笑)

言归正传,感觉这道数位 DP 非常神奇。我们考虑到其实各个数位之和比较小,可以直接枚举。

这样就解决了一个重要的问题:我们的“数”范围太大,状态装不下。(不过注意要保证解的各个数位之和等于模数)

直接套数位 DP 板子即可。

\(Code\)

#pragma GCC optimize(2)
#include <cstdio>
#include <cstring>
typedef long long ll;

int a[20];
ll dp[20][200][200], mod;

ll read() {
    ll x = 0, f = 1; char s;
    while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
    while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
    return x * f;
}

ll DP(const int p, const int s, const int sta, const bool lim) {
    if(p == -1) return sta == 0 && s == mod;
    if(! lim && (~ dp[p][s][sta])) return dp[p][s][sta];
    int up = lim ? a[p] : 9; ll ans = 0;
    for(int i = 0; i <= up; ++ i)
        ans += DP(p - 1, s + i, (1ll * sta * 10 + i) % mod, lim && i == up);
    return lim ? ans : dp[p][s][sta] = ans;
}

ll get(ll x) {
    int p = -1; ll ans = 0;
    while(x) {a[++ p] = x % 10; x /= 10;}
    for(mod = 1; mod <= (p + 1) * 9; ++ mod) memset(dp, -1, sizeof dp), ans += DP(p, 0, 0, 1);
    return ans;
}

int main() {
    ll a = read(), b = read();
    printf("%lld\n", get(b) - get(a - 1));
    return 0;
}

【AHOI 2009】同类分布

标签:状态   memset   include   ++   return   const   type   cstring   size   

原文地址:https://www.cnblogs.com/AWhiteWall/p/12525786.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!