1. 程式人生 > >數位dp詳解及模板

數位dp詳解及模板

數位dp一般應用於:
求出在給定區間[A,B]內,符合條件P(i)的數i的個數.條件P(i)一般與數的大小無關,而與 數的組成有關.
比如說在HDU2089中, 讓求區間內數中不有462的數字個數之和

對於此類問題,我們一般設dp陣列dp[i][j],表示i位數,最高位是j的數,不含有624的數有多少個
對於上述不含有624的要求,遞推式如下

這裡寫圖片描述
換成程式碼就是:

if(j==4)
    dp[i][j] = 0;
else{
    for(int k=0;j<=9;k++){
        if(j==6&&k==2
) continue; dp[i][j] += dp[i-1][k]; } }

到此,我們就能求對於所有能被10整除的滿足條件的數的個數了
而對於任意數x,只需要將其拆成x=x1100+x2101+x3102+......的形式即可
然後求出xy的個數,相減便是答案

#include <map>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring> #include <iostream> #include <algorithm> #define IN freopen("in.txt","r",stdin) #define OUT freopen("out.txt","w",stdout) #define IO do{\ ios::sync_with_stdio(false);\ cin.tie(0);\ cout.tie(0);}while(0) using namespace std; typedef long long ll; const int
maxn = 1e4+10; const int MAXN = 1e6+10; const int INF = 0x3f3f3f3f; const int inf = 0x3f; const double EPS = 1e-7; const double Pi = acos(-1); const int MOD = 1e9+7; int dp[15][15]; int num[15]; void init() { dp[0][0] = 1; for(int i=1; i<=9; i++) for(int j=0; j<=9; j++) { if(j==4) dp[i][j] = 0; else for(int k=0; k<=9; k++) { if(j==6&&k==2) continue; dp[i][j] += dp[i-1][k]; } } } int ask(int x) { ll ans = 0; int cnt = 0; while(x) num[++cnt] = x%10,x/=10; num[cnt+1] = 0; for(int i=cnt; i>=1; i--) { for(int j=0; j<num[i]; j++) { if(j==4||(j==2&&num[i+1]==6)) continue; ans += dp[i][j]; } if(num[i] == 4||(num[i]==2&&num[i+1]==6)) break; } return ans; } int main() { IO; //IN; int n,m; init(); while(cin >> m >>n &&(n||m)) cout <<ask(n+1)-ask(m)<<endl; return 0; }