【學習筆記】數位DP

SDFZ_GuoSN發表於2024-09-17

數位DP

適用條件

此類題目一般要求在\([l,r]\)區間內滿足條件的數的個數,答案一般與數的大小無關,而與數各位的組成有關。題目中給出的數的範圍一般較大,往往在\(10^9\)以上因此無法暴力列舉,只能使用動態規劃

程式碼實現

使用記憶化搜尋更簡單易於理解。
從數的高位向低位搜尋,每一位可以為\(0-9\)。但是注意當搜尋到第\(i\)位時,如果前\(i-1\)位已經是最大值時,那麼當前的數也不能超過最值,即範圍為

\[0-a[i] \]

因此記憶化搜尋函式需要兩個引數。
1.\(cur\)表示當前位於第\(cur\)
2.\(lim\)表示前\(cur-1\)是否已經全部達到最大值。\(lim_{cur+1}==1\),當且僅當

\[lim_{cur}==1,i==max \]

因為題目要求\([l,r]\)區間內滿足條件的個數,由於個數滿足區間可加性,因此可以用類似字首和的方法來求。設\(calc(i)\)表示\(0-i\)區間內的個數,那麼答案就是\(calc(r)-calc(l-1)\)

\(ACcode\)

\(DFS code\)

int dfs(int x,bool lim){
	if(x<=0)return 1;
	if(!lim&&f[x]!=-1)return f[x];
	int up=lim?a[x]:9;
	int ans=0;
	for(int i=0;i<=up;i++){
		if(i!=4)ans+=dfs(x-1,lim&&(i==up));
	}
	if(!lim)f[x]=ans;
	return ans;
}

初始化+\(calc\ code\)


int calc(int x){
	len=0;
	memset(f,-1,sizeof(f));
	while(x){
		a[++len]=x%10;
		x/=10;
	}
	return dfs(len,1);
}

相關文章