前言
上學期差不多整個學期都在打各種比賽,幾乎沒學新演算法,因此寒假好好補一波演算法,不過數字dp入個門也花了我兩天,學習效率還沒回來… …模板題
題目鏈結
給定乙個數字區間[l,r],問你區間內有多少數不含4,也不含連續的62。
題目範圍是1e7,可以on預處理+字首和o1查詢,**就不放了。
數字dp
今天的重點是數字dp。
數字dp的好處在於直接對位進行暴力,另外加上記憶化,可以大大減少時間。例如列舉千位時,一次列舉就相當於暴力下的一千次列舉。
初學數字dp,我感覺他的本質就是記憶化搜尋。因此先上無記憶化的搜尋**:
#include
using
namespace std;
int a[20]
, pos;
intdfs
(int pos,
int sta,
int lim)
//列舉到第pos位,上一位是否是6,該位是否有約束
return sum;
}int
solve
(int mx)
return
dfs(pos,0,
1);}
intmain()
上面這份**的寫法其實比較奇怪,算是半個數字dp的寫法吧。其中的lim是數字dp中乙個關鍵點,可以看底下的參考部落格理解。
這份**本質上就是暴力,如果查詢次數多或者資料範圍加到1e9以上肯定是會tle的,但是加上記憶化就不一樣了,記憶化可以剪掉一大部分遞迴棧。記憶化只多了四五行**:
/*
* @author: hesorchen
* @date: 2020-12-30 16:53:18
* @lastedittime: 2021-01-12 21:17:10
* @description: 栽種絕處的花
*/#include
using
namespace std;
int a[20]
, pos;
int dp[20]
[2];
intdfs
(int pos,
int sta,
int lim)
//列舉到第pos位,上一位是否是6,該位是否有約束if(
!lim)
//記憶化
dp[pos]
[sta]
= sum;
return sum;
}int
solve
(int mx)
return
dfs(pos,0,
1);}
intmain()
這裡的記憶化需要判斷!limit,這是乙個稍難的點,事實上,就是為了避免limit
或者非limit
兩種狀態的衝突,經過實測,我們完全可以記憶化中的一種,不過就此題來說,顯然!limit的狀態更多,因此選擇記憶這種效率更高。具體理解看底下的參考部落格吧。
參考部落格
數字dp總結 之 從入門到模板
HDU2089 不要62 數字DP
problem description 杭州人稱那些傻乎乎粘嗒嗒的人為62 音 laoer 杭州交通管理局經常會擴充一些的士車牌照,新近出來乙個好訊息,以後上牌照,不再含有不吉利的數字了,這樣一來,就可以消除個別的士司機和乘客的心理障礙,更安全地服務大眾。不吉利的數字為所有含有4或62的號碼。例如 ...
Hdu2089 不要62 數字dp
include includeint dp 10 3 dp i 0 為位數小於等於i且不含62也不含4的數字的個數 dp i 1 為位數為i且首位為2且不含62也不含4的數字的個數 dp i 2 為位數小於等於i且含62或4的數字的個數 int digit 10 void er int wei in...
hdu 2089 不要62 (數字dp)
思路 用變數記錄吉利數,和最高位為2的吉利數還有不是吉利數的個數。code include include includeusing namespace std int dp 10 3 dp i j i表示位數,j表示狀態 dp i 0 表示不存在不吉利數字 dp i 1 表示不存在不吉利數字,且最...