hdu5787 數字dp 數字壓縮

2021-07-16 02:51:04 字數 1948 閱讀 4887

分析

大概是比較經典的數字dp,需要維護連續的

k 個數字不相同,所以我們的狀態記錄裡需要記錄前k−

1個數字是哪些,擴充套件下一位的時候不能出現前k−

1 位的數字。

這樣就來設計狀態:dp

[len

][k]

[ban

] ,表示前長度為le

n ,連續的

k 個字元禁止出現相同,前k−

1個數字為ba

n 。

這裡的ban

用了數字壓縮的技巧,比如前

3 個數字為4,

2,5,那麼我的ba

n 就是10進製數

425 。

到這裡賽場上都很容易想到,但是由於處理前到零一直debug了我

4 個小時才對,還增加了乙個維度作為記錄連續的多少位內禁止出現0。

一言不合就加維度!

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef pair pii;

typedef

long

long ll;

typedef

unsigned

long

long ull;

vector

vi;

#define pr(x) cout << #x << ": " << x << " "

#define pl(x) cout << #x << ": " << x << endl

#define xx first

#define yy second

#define sa(n) scanf("%d", &(n))

#define rep(i, a, n) for (int i = a; i < n; i++)

#define vep(c) for(decltype((c).begin() ) it = (c).begin(); it != (c).end(); it++)

#define limit asdf

const

int mod = int(1e9) + 7, inf = 0x3fffffff, maxn = 1e5 + 12;

int t;

ll dp[19][4][9876 + 7][5];

int bits[25];

ll l, r;

int k;

ll dfs(int len, int ban, bool limit, int k, int go, int zero, bool pre)

if (!pre && zero > 0) no[0] = true;

for (int i = 0; i <= m; i++)

ret += dfs(len - 1, nxt, limit && i == m, k, go + 1, nxtzero, pre && !i);

}if (!pre && !limit) dp[len][k - 2][ban][zero] = ret;

return ret;

}//常規套路

ll solve(ll n)

ll ret = dfs(t - 1, 0, true, k, 0, 0, true);

return ret;

}int main(void)

return

0;}

2016ACM多校 HDU5787 數字DP

求 l,r 中這樣一種數的個數,它的每連續k位都滿足兩兩不相同。2 k 5 k很小,典型的數字動態規劃,為了方便寫成記憶話搜尋的形式。從高位往低位決策,傳入之前臨近的k位是哪些數,這一位是否可以自由列舉0 9,是否來自前導零。為了修改最近的k位所占用的數,要用乙個佇列或者其他資料結構維護填數的先後順...

hdu4352 數字dp 狀態壓縮

題意 給出l和r找出在 l,r 中滿足最長遞增子串行長度等於k的個數。題解 狀壓想不到,看了kuangbin的才明白,1 10狀壓存數出現了沒有。利用了nlogn遞增字序列演算法的思想。include include include include includeusing namespace st...

HDU 4352(數字dp 狀態壓縮 LIS)

求區間範圍內最長上公升子串行數字k的數字有多少個 首先由數字dp引入思路,dp轉移方程為 dfs pos,status.累加dfs pos 1,stautselse 可備忘錄記錄的dp陣列為 dp pos status k 之所以要備忘錄k,是為了滿足不同k的訪問 status記錄的是開頭數字到po...