HDU 不要62 題解

FRZ_29發表於2024-08-11

題目傳送門

思路

數位 dp

數位 dp

數位 dp 模版題。

依次考慮每一位,滿足題目給出的限制,統計數量,是一些較簡單的數位 dp 題目的過程。

數位 dp 運用了差分的思想,即求 \(ans(l - r)\) 的答案用 \(ans(1 - r) - ans(1-(l - 1))\) 來表示.

對於本題,我們需要滿足的性質很簡單:

  1. 使數不超過上界,如求 \([5 - 1000]\) 不能使 \(1005\)
  2. 考慮到某一位時,如果其前一位為 \(6\),那麼則一位不能為 \(2\),如果這一位填了 \(6\),下一位不能填 \(2\)
  3. 任何一位不能是 \(4\)

條件 1 是數位 dp 的常規操作,條件 2 和 條件 3 均可以在 dp 過程中透過檢查標記來滿足。

具體見程式碼。

程式碼

點選檢視程式碼
/*
  --------------------------------
  |        code by FRZ_29        |
  |          code  time          |
  |          2024/08/11          |
  |           16:09:04           |
  |             星期天            |
  --------------------------------
                                  */

#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <ctime>

using namespace std;

void RD() {}
template<typename T, typename... U> void RD(T &x, U&... arg) {
    x = 0; int f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    x *= f; RD(arg...);
}

const int N = 1e6 + 5, M = 10;

#define LF(i, __l, __r) for (int i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (int i = __r; i >= __l; i--)

int n, m, num[N];
int f[M][2][2];

int dfs(int u, bool lim, bool lim_6) { // lim 為條件 1 的限制,lim_6 為條件 3 的限制
    if (u == 0) return 1;
    if (f[u][lim][lim_6] != -1) return f[u][lim][lim_6]; // 記憶化搜尋能最佳化時間複雜度
//    printf("u = %d, lim = %d, lim_6 = %d\n", u, lim, lim_6);
    int up = (lim ? num[u] : 9);
    f[u][lim][lim_6] = 0;
    LF(i, 0, up) {
        if (i == 4 || (lim_6 && i == 2)) continue;
        f[u][lim][lim_6] += dfs(u - 1, lim == true & i == up, i == 6);
    }
    return f[u][lim][lim_6];
}

int calc(int n) {
    if (n < 0) return 0;
    int tmp = n;
    int cnt = 0;
    while (tmp) num[++cnt] = tmp % 10, tmp /= 10;
    LF(i, 1, cnt) LF(j, 0, 1) LF(k, 0, 1) f[i][j][k] = -1;
    return dfs(cnt, 1, 0);
}

int main() {
    // freopen("read.in", "r", stdin);
    // freopen("out.out", "w", stdout);
    // time_t st = clock();
    while (RD(n, m), n, m) printf("%d\n", calc(m) - calc(n - 1));
    // printf("\n%dms", clock() - st);
    return 0;
}

/* ps:FRZ弱爆了 
 * 這是 FRZ 第 1 道數位 dp 題
 * FRZ做的太少了(悲
 * 真是弱爆了
 */

在逆風裡把握方向,做暴風雨中的海燕,做不改顏色的孤星。

相關文章