[CQOI2016]手机号码

Description

BZOJ4521
Luogu4124
求在\([l,r]\)中有多少个数字满足有3个连续相同数位且不同时出现4和8。

Solution

直接数位DP。

Code

#include <cstdio>
#include <algorithm>
#include <cstring>

typedef long long LL;

LL dp[20][20][20][20][20];
LL a[20];

LL dfs(int pos, int used, int last, int len, bool lead, bool limit, int mxln) {
    
    if (pos == -1) return mxln >= 3;
    if (!lead && !limit && dp[pos][used][last][len][mxln] != -1) 
        return dp[pos][used][last][len][mxln];
    int up = limit ? a[pos] : 9;
    LL ans = 0;
    for (int i = lead; i <= up; ++i) {
        if ((used == 4 && i == 8) || (used == 8 && i == 4)) continue;
        ans += dfs(pos-1, i==4||i==8 ? i : used, i, i==last?len+1:1, 0, limit&&i==a[pos], std::max(mxln, len+(i==last)));
    }
    if (!lead && !limit) dp[pos][used][last][len][mxln] = ans;
    return ans;
}

LL calc(LL x) {
    int pos = -1;
    while (x) {
        a[++pos] = x % 10L;
        x /= 10L;
    }
    LL ans = pos != 10 ? 0 : dfs(pos, 0, 0, 0, true, true, 0);
    return ans;
}

int main() {
    memset(dp, -1, sizeof dp);
    LL l, r;
    scanf("%lld%lld", &l, &r);
    printf("%lld\n", calc(r) - calc(l-1));
    return 0;
}

Note

不要忘了初始化dp啊!!

posted @ 2018-09-12 19:46  wyxwyx  阅读(99)  评论(0编辑  收藏  举报