題目傳送門
思路
數位 dp
數位 dp
數位 dp 模版題。
依次考慮每一位,滿足題目給出的限制,統計數量,是一些較簡單的數位 dp 題目的過程。
數位 dp 運用了差分的思想,即求 \(ans(l - r)\) 的答案用 \(ans(1 - r) - ans(1-(l - 1))\) 來表示.
對於本題,我們需要滿足的性質很簡單:
- 使數不超過上界,如求 \([5 - 1000]\) 不能使 \(1005\)
- 考慮到某一位時,如果其前一位為 \(6\),那麼則一位不能為 \(2\),如果這一位填了 \(6\),下一位不能填 \(2\)。
- 任何一位不能是 \(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做的太少了(悲
* 真是弱爆了
*/
在逆風裡把握方向,做暴風雨中的海燕,做不改顏色的孤星。