HDU3555 Bomb problem stops bit DP

Link Title: http://acm.hdu.edu.cn/showproblem.php?pid=3555
Title effect: seeking \ ([1, n] \ ) in a range comprising a plurality few "49."
Problem-solving ideas:
This is something we can be divided into two solutions to consider: the first is seeking does not include the number of the number "49" after reducing it by; the other is the direct request contains the number of the number "49" is.

Solution 1: Find the number does not include the number "49"

By this method we first determined the number of bits the DP \ ([0, n-] \) interval does not include the range of a small number of multiple "49" (the number is assumed to be \ (X \) ), then the answer is \ (n + -the X-1 \) .

We can design a function dfs(int pos, int stat, bool limit)that returns the interval \ ([0, n] \ ) in the range of a few does not contain a number, "49", wherein:

  • pos It represents the digit is currently located;
  • stat Pre represents a number is not '4' (if the former is '4' is the current location '9' to make up the "49");
  • limit For labeling currently restricted (true: Restricted; false: unlimited).

Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
long long f[66][2], n;
int T, a[66];
void init() {
    memset(f, -1, sizeof(f));
}
long long dfs(int pos, int stat, bool limit) {
    if (pos < 0) return 1;
    if (!limit && f[pos][stat] != -1) return f[pos][stat];
    int up = limit ? a[pos] : 9;
    long long tmp = 0;
    for (int i = 0; i <= up; i ++) {
        if (stat && i == 9) continue;
        tmp += dfs(pos-1, i==4, limit && i == up);
    }
    if (!limit) f[pos][stat] = tmp;
    return tmp;
}
long long get_num(long long x) {
    int pos = 0;
    while (x) {
        a[pos++] = x % 10;
        x /= 10;
    }
    return dfs(pos-1, 0, true);
}
int main() {
    init();
    scanf("%d", &T);
    while (T --) {
        scanf("%lld", &n);
        printf("%lld\n", n+1-get_num(n));
    }
    return 0;
}

Solution 2: Please include how many number "49"

Solution 1 is relatively indirect way to solve it. We are now in this way is directly solving \ ([0, n] \ ) within a range of how many contain the number "49."

We can design a function dfs(int pos, int stat, bool limit)that returns the interval \ ([0, n] \ ) in the range of a few does not contain a number, "49", wherein:

  • pos It represents the digit is currently located;
  • stat Pre represents a number is not '4' (if the former is '4' is the current location '9' to make up the "49");
  • limit For labeling currently restricted (true: Restricted; false: unlimited).

Although it is the same, but when dealing with statistics is not the same way.

It should be noted in particular restrictions under different processing conditions and non-limiting.

Suppose we are looking for is the interval \ ([0, n] \ ) in a range comprising a plurality few "49" is traversed posbits and pos+1bits are '4', posthe bit is '9', then we can see that:

  1. If the current state is the limit, then there is \ (n \% 10 ^ { pos} + 1 \) number satisfying the condition;
  2. If the current state is in a non-limiting, the following has \ (10 ^ {pos} \ ) number satisfying the condition.

Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
long long f[66][2], n;
int T, a[66];
void init() {
    memset(f, -1, sizeof(f));
}
long long pow10(int a) {
    if (a == 0) return 1;
    if (a == 1) return 10;
    long long t = pow10(a/2);
    return t * t * (a%2 ? 10 : 1);
}
long long dfs(int pos, int stat, bool limit) {
    if (pos < 0) return 0;  // 返回0说明没找到包含49的
    if (!limit && f[pos][stat] != -1) return f[pos][stat];
    int up = limit ? a[pos] : 9;
    long long tmp = 0;
    for (int i = 0; i <= up; i ++) {
        if (stat && i == 9) {   // 说明接下来pos位的10的pos次方个数都满足条件
            // tmp += pow10(pos);   // 直接这么写是错的,此时也要考虑边界条件限制
            // 修正如下
            if (limit) tmp += n % pow10(pos) + 1;
            else tmp += pow10(pos);
        }
        else tmp += dfs(pos-1, i==4, limit && i == up);
    }
    if (!limit) f[pos][stat] = tmp;
    return tmp;
}
long long get_num(long long x) {
    int pos = 0;
    while (x) {
        a[pos++] = x % 10;
        x /= 10;
    }
    return dfs(pos-1, 0, true);
}
int main() {
    init();
    scanf("%d", &T);
    while (T --) {
        scanf("%lld", &n);
        printf("%lld\n", get_num(n));
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/quanjun/p/11964644.html