數位DP 學習筆記

Wh1sky發表於2024-03-06

什麼是數位DP

數位dp是與數字相關的一類計數問題。這這類問題中,一般給定一些限制條件,求滿足第 \(K\) 小的數是多少,或者求區間 \([L,R]\) 內有多少個滿足條件的數。

本文主要講述如何解決 求區間 \([L,R]\) 內有多少個滿足條件的數 這一類問題。

為什麼要用數位dp

對於上述問題,如果只使用簡單的暴力,時間複雜度為 \(O(n+?)\) 列舉的時間複雜度 + 驗證的時間複雜度。

如果採用 \(dfs\) 列舉每一位的方法。則可以透過題目已有條件,進行一部分的剪枝。程式碼如下

#include <bits/stdc++.h>
using namespace std;

const int N = 20;

int num[N];

int dfs(int len, bool limit, bool lead, /*一些引數記錄是否符合條件*/) {
	//limit表示當前的最高數是否有限制 lead表示前導0 
	if(len == 0) return sum;
	int ans = 0;
	int maxx = limit ? num[len]:9; 
	for (int i = 0; i <= maxx; i++) {
		ans += dfs(len-1, limit&&(i==maxx), lead||i, /*一些引數*/);
	}
	return ans;
}

int work(int x, int i) {
	int len = 0;
	while (x) {
		num[++len] = x%10;
		x /= 10;
	}
	memset(f, -1, sizeof(f));
	return dfs(len, 1, 0, i, 0);
}
int main() {
	int a, b;
	scanf("%d %d", &a, &b);
	for (int i = 0; i <= 9; i++) {
		printf("%d ", work(b, i) - work(a-1, i));
	}
	return 0;
}

詳解 \(limit\)\(lead\)

\(limit\) 記錄當前列舉到當前數位,是否有最高位限制。對於每個數位的最大數不一定為 \(9\) 。舉個荔枝 對於區間 \([5,114514]\) ,我們列舉到 \(1?????\) 顯然當前數位列舉的最大數不應該為 \(9\) ,要不然我們列舉出的數就會超過區間限制。

\(lead\) 記錄當前數位的前一位是否為前導 \(0\) , 這一項的記錄有時候並不是必要的。你需要根據題目來設計你的狀態。

可這樣時間複雜度仍舊不盡人意。

怎麼用數位dp

我們觀察到,有很多等價的狀態被重複遍歷。舉個例子 \(114???\) ,和 \(124???\) 兩個狀態(在他們沒有最大數限制的情況下),列舉接下來數位數字的狀態樹一定是相同的。那還有必要在重複列舉兩個相同的子樹嗎?答案是顯然的。所以我們可以透過記憶化來避免多次遍歷相同的 \(dfs\) 子樹。
程式碼如下

#include <bits/stdc++.h>
using namespace std;

const int N = 15;

int a, b;
int num[N],f[N][N];

int dfs(int len, bool limit, bool lead, /*一些引數記錄是否符合條件*/) {
	if(len == 0) {
		if(!lead) return 0;
		return 1;
	}
	if(!limit&& /*根據題目自定引數*/) return f[][];
	
	int ans = 0;
	int maxx = limit ? num[len]:9;
	for (int i = 0; i <= maxx; i++) {
		ans += dfs(len-1, limit&&(maxx==i), lead||i, /*一些引數記錄是否符合條件*/);
	}
	if(!limit&&lead) f[len][last] = ans;
	return ans;
}

int solve(int x) {
	memset(f, -1, sizeof(f));
	int len = 0;
	while (x) {
		num[++len] = x%10;
		x /= 10;
	}
	if(len==0) return 0;
	return dfs(len, 1, 0, -2);
}
int main() {
	scanf("%d %d", &a, &b);
	printf("%d", solve(b)-solve(a-1));
	return 0;
}

參考資料

  • [洛穀日報第84期]數字組成的奧妙——數位dp
  • 演算法學習筆記(22):數位DP(數位動態規劃)

相關文章