數字dp,即對數字進行拆分,利用數字來轉移的一種dp,一般採用記憶化搜尋,或者是先預處理再進行轉移
乙個比較大略的思想就是可以對於給定的大數,進行按數字進行固定來轉移記錄答案
區間型別的,可以考慮字首和的思想,求[l,r]可以看做求[1,r]-[1,l)
其實還有一種,是按照二進位制建一顆0,1樹來表示,來做,但是比並沒有做過,以後再總結
hdu-2089
題目大意:對於區間[l,r]求有多少不包含'62'且不包含'4'的數,題目允許有前導零
思路:
數字dp,考慮f[i][j]表示位數為i,最高位為j的滿足的個數
預處理後,統計答案即可,統計答案大致就是固定每一位,進行統計
code:
#include#include#include
#include
#include
using
namespace
std;
intread()
while (ch>='
0' && ch<='
9')
return x*f;
}int
n,m;
int f[10][10
];void
prework()
int calc(int
x),len=0,ans=0
;
while (x!=0)
for (int i=len; i>=1; i--)
return
ans;
}int
main()
return0;
}
hdu-3652
題目大意:給定n,求到n中,包含'13'且被13整除的數的個數
思路:
設計狀態f[i][j][k][0/1]表示位數為i,最高位為j的%13餘k的數字包含和不包含13的個數
那麼同樣預處理,這裡不含前導零,需要額外做乙個值去進行計算,計算到n以內的,計算n+1即可
code:
#include#include#include
#include
#include
using
namespace
std;
long
long
n;long
long f[20][20][15][2
];long
long cf(int x,int
y)void
prework()
}//for (int i=1; i<=10; i++)
//for (int j=0; j<=9; j++)
//for (int k=0; k<13; k++)
//printf("%i64d %i64d\n",f[i][j][k][1],f[i][j][k][0]);
}long
long calc(long
long
x),len=0,f=0; long
long ans=0
;
while (x)
for (int i=0; i<=digit[len]-1; i++)
ans+=f[len][i][0][0
];
long
long tmp=cf(digit[len],len-1
);
for (int tt,i=len-1; i>=1; i--)
if (digit[i]==3 && digit[i+1]==1) f=1
; tmp+=cf(digit[i],i-1
); }
return
ans;
}int
main()
HDU訓練記錄2 基礎數字dp
題目描述 傳送門題意 求0 n中含 49 的數的個數。題解狀態 f i j 表示i位數所有以j開頭的數中合法 不含 49 的數的個數。轉移 if j 4 k 9 f i j f i 1 k 列舉jk分別為i和i 1位數的開頭並且滿足條件。求解時用總數減去dp值。注意 這道題傳m 1的話有可能爆lon...
數字dp學習筆記
我們通常使用字首和的思想和記憶化搜尋來實現數字 dp。就是上面所說的常見問法。例題 windy 數 int dfs int k,int x,int p,int q if p q f k x res return res 這道題的難點就在於對相鄰兩個數字之差至少為 2 的處理,我們一開始將 x 設為 ...
DP專題 學習筆記 數字 DP
目錄3.練習題 update 2021 2 23 最近作者發現數字 dp 的 f 陣列初始化有問題,導致 出現了根本性錯誤 原理不變 現在已經糾正,對各位讀者造成的困擾深表歉意。數字 dp,是一種 dp 廢話 專門用於數字統計類問題。這種問題首次接觸可能會有些難理解,但是練過幾道題之後就會掌握套路了...