數位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);
}