首先根據題目的要求初始化
一般為:
for(int i = 0;i <= 1;i ++) dp[1][i] = 1;
for(int i = 1;i <= 最大數的位數;i ++)
for(int j = 0;j <= 9;j ++)
for(int k = 0;k <= 9;k ++)
if(......)//題目要求
dp[i][j] += dp[i-1][k];
dp[i][j]表示不大於位數為i且最高位為j的方案總數。
但是對於最高位,我們並不總是能取得以它為開頭的全集(19999……這一類除外)
不過,如果去掉最高位,我們所列舉的數都是合法的。所以可以直接列舉每一位1 ~ 9的答案就好了。
對於其他的數如果我們沒有方法直接統計,或許我們要想辦法把他拆開。
舉個例子,對於 24653這組數。
因為我們有5位數,所以對於前四位是一定會包含的。
所以我們列舉之前每一位數以1~9為最高位的答案(若不允許含前導0)。
在這裡,對於最高位,我們只加上以1位最高位的答案。(因為以2為最高位並不能列舉到所有的數)
然後我們假定最高位為2,加上次高位以0~3為下一位的答案。
然後我們假定前面的數為24,……
然後對於最後一位的3我們怎麼處理,難道這個3不要了?
那就不要了吧,寫開區間吧,我們求24654這個數。
對了,有乙個細節,如果對於某一枚舉的數字自身已經不符合要求了。
由於我們的每一位都會帶到下一位,所以後面的一定不符合條件,要直接跳出。
例如我們要求不大於某乙個數中相鄰兩個數不大於2的個數,對於12347666這個數如果我們已經假定前幾
位分別是12347,那麼對於後面的數無論我們選什麼都是不成立的,所以直接break;
#include
#include
#include
#include
#include
using
namespace
std;
int a,b,ans,cnt,jl[105],dp[105][105];
void init()//數字dp的套路,按照題目要求初始化。
int tj(int x)//這是乙個開區間的。
//拆分x
for(int i = 1;i < cnt;i ++)
for(int j = 1;j <= 9;j ++)
ans += dp[i][j];//如果去掉最高位,我們所列舉的數都是合法的。
for(int i = 1;i < jl[cnt];i ++) ans += dp[cnt][i];//最高位到第jl[cnt-1]位為止還是全集。
for(int i = cnt - 1;i >= 1;i --)//假設上一位已經確定為jl[i+1]。
return ans;
}int main()
HDU 3652 數字DP 套路題
題意 統計能被13整除和含有13的數的個數 解法沒法好說的.學了前面兩道直接啪出來了 ps.hdu深夜日常維護,沒法交題,拿網上的 隨便對拍一下,輸出一致 include define rep i,j,k for register int i j i k i using namespace std ...
HDU 1520 樹形dp裸題
1 hdu 1520 anniversary party 2 總結 第一道樹形dp,有點糾結 題意 公司聚會,員工與直接上司不能同時來,求最大權值和 include include include include include include define max a,b a b?a b usin...
數字dp 板子題
題目傳送 存乙個狀態就可以了,用來判斷前一位是不是6的情況 具體看 注釋 ac include inline long long read while c 0 c 9 return x s using namespace std define newnode treenode malloc size...