【数位DP】二四六七八

二四六七八

题意:对于每组数据给定的 \(x\)\(y\) , 求 \([x,y]\) 内各个数位仅由 \(2,4,6,7,8\) 构成的数的个数。其中\(1≤x≤y≤10^{18}\)

思路:
算是板子题。卡住的点主要还是不清楚什么时候前导零是必须的。
另外不开longlong见祖宗

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

LL dfs(int pos,bool lead,bool limit){
    LL ans = 0;
    if (pos == -1) return 1;
    if (!limit && !lead && dp[pos] != -1) return dp[pos];
    int end = limit ? a[pos] : 9;
    for (int i = 0; i <= end; i++) {
        if (i == 1 || i == 3 || i == 5 || i == 9) continue;
        if (!lead && (!i)) continue;
        //0是不合法的,如果没有前导零,这一位又是零,就跳过
        ans += dfs(pos - 1, lead&&(!i), limit && i == end);
        //如果有前导零且这一位也是零,那么这一位也是前导零
        //否则如果有前导零且这一位不是零,则不是前导零
    }
    if (!limit&&!lead)  dp[pos] = ans;
    //没有前导零也没有最高位限制,说明本次统计结果是通用的
    return ans;
}

LL part(LL x){
    int len = 0;
    LL k = x;
    while (k) {
        a[len++] = k % 10;
        k /= 10;
    }
    memset(dp, -1, sizeof (dp));
    return dfs(len - 1, true, true);
}

int main()
{
    ios::sync_with_stdio(false);
    int t; cin >> t; while (t--){
       LL l, r;
       cin >> l >> r;
       cout << part(r) - part(l-1)<<endl;
    }
    return 0;
}
posted @ 2020-06-05 03:01  StreamAzure  阅读(122)  评论(0编辑  收藏  举报