CF55D Beautiful numbers (数位dp)

Topic Link

answer

Some can be a number divisible, then it must be these numbers \ (lcm \) divisible

So we tend to think according to \ (lcm \) set state

We might find it useful \ (lcm \) only \ (48 \) a

Well, according to the average number of bits \ (dp \)

Setting a state: \ (F_ {I, J, K, 0 /. 1} \) representing the forward \ (I \) bit, \ (LCM = J \) , die \ (LCM \) of the remainder is \ (K \ ) , whether the upper bound

But this way can not be transferred (because of a number of newly added module may produce changes)

So we have unified into a module \ (2520 \)

Complexity \ (O (T * L * 48 * 2500 * 2) \)

Wherein \ (L \) is the number of input bits

Then it will \ (TLE \)

Consider it a little optimization.

Because multiple sets of questions.

If you've asked a great number of,

This time there are actually asking a lot of answers we already know.

We can get rid of the state \ (01 \) that dimension.

Such complexity can remove a number of the group asked.

See specific second code.

Code

int gcd(int x, int y) {
    return !y ? x : gcd(y, x % y);
}
int lcm(int x, int y) {
    if (!x || !y) return x | y;
    return x * y / gcd(x, y);
}
LL dfs(int x, int n, int m, int op) {
    if (!x) return !num[n] || m % num[n] == 0;
    if (f[x][n][m][op] != -1) return f[x][n][m][op];
    LL &res = f[x][n][m][op]; res = 0;
    for (int i = 0; i <= (op ? a[x] : 9); i++)
        res += dfs(x - 1, M[lcm(num[n], i)], (m * 10 + i) % 2520, op & i == a[x]);
    return res;
}
LL calc(LL x) {
    if (!x) return 1;
    l = 0;
    while (x) a[++l] = x % 10, x /= 10;
    for (int i = 1; i <= l; i++)
        memset(f[i], -1, sizeof(f[i]));
    return dfs(l, 0, 0, 1);
}
void solve() {
    LL l = gi<LL>(), r = gi<LL>();
    printf("%lld\n", calc(r) - calc(l - 1));
    return ;
}
int main() {
    for (int i = 1; i < (1 << 9); i++) {
        int d = 0;
        for (int j = 0; j < 9; j++)
            if (i >> j & 1)
                d = lcm(d, j + 1);
        if (!M[d]) num[++cnt] = d, M[d] = cnt;      
    }
    int T = gi<int>();
    while (T--) solve();
    return 0;
}
LL dfs(int x, int n, int m, int op) {
    if (!x) return !num[n] || m % num[n] == 0;
    if (!op && f[x][n][m] != -1) return f[x][n][m];
    LL res = 0;
    for (int i = 0; i <= (op ? a[x] : 9); i++)
        res += dfs(x - 1, M[lcm(num[n], i)], (m * 10 + i) % 2520, op & i == a[x]);
    if (!op) f[x][n][m] = res;
    return res;
}

Guess you like

Origin www.cnblogs.com/zzy2005/p/11716587.html