數字dp入門刷題記錄

2021-10-09 22:38:46 字數 4860 閱讀 7209

數字dp的一些基礎元素:

pos:位數,lead:前導零判斷,limit:數字上界變數

pre:前乙個數,state:當前狀態(一般與pre重合)

兩個函式:dfs(遞迴,dp)+solve(數拆分)

分享一篇部落格

unsigned

int0~4294967295

int-

2147483648~2147483647

unsigned

long

0~4294967295

long

-2147483648~2147483647

long

long的最大值:9223372036854775807

long

long的最小值:-

9223372036854775808

unsigned

long

long的最大值:1844674407370955161

__int64的最大值:9223372036854775807

__int64的最小值:-

9223372036854775808

unsigned __int64的最大值:18446744073709551615

對比

2^30

-->

1e9int

-->

2e92^60

-->

1e18 ll --

>

9e18

一般開35就夠了,dp用int

入門題:hdu 2089 不要62

無前導零考慮,基礎思考方式。

#include

#pragma gcc optimize(2)

using

namespace std;

typedef

long

long ll;

const

int inf=

0x3f3f3f3f

;const

int mod=

1e9+7;

const

int maxn=

1e3+7;

int n,m,cnt;

int a[30]

,dp[30]

[2];

intdfs

(int pos,

int pre,

int x,

bool limit)if(

!limit) dp[pos]

[x]=ans;

return ans;

}int

solve

(int x)

return

dfs(pos-1,

-1,0

,1);

}int

main()

return0;

}

簡單題:

hysbz 1026 windy數

注意前導零操作

#include

#pragma gcc optimize(2)

using

namespace std;

typedef

long

long ll;

const

int inf=

0x3f3f3f3f

;const

int mod=

1e9+7;

const

int maxn=

1e3+7;

ll n,m,cnt;

ll a[30]

,dp[30]

[10];

ll dfs

(int pos,

int pre,

bool lead,

bool limit)if(

!limit) dp[pos]

[pre]

=ans;

return ans;

}int

solve

(int x)

return

dfs(pos-1,

-1,1

,1);

}int

main()

return0;

}

還有普通dp預處理,有前導零時,可能出漏情況的錯誤,還是少寫吧。

#include

#pragma gcc optimize(2)

using

namespace std;

typedef

long

long ll;

const

int inf=

0x3f3f3f3f

;const

int mod=

1e9+7;

const

int maxn=

1e3+7;

ll n,m,cnt;

ll a[14]

,dp[14]

[10];

void

init()

intsolve

(int x)

a[cnt+1]

=0;for

(int i=

1;i)for

(int j=

1;j<=

9;j++

) ans+

=dp[i]

[j];

for(

int i=

1;i;i++

) ans+

=dp[cnt]

[i];

for(

int i=cnt-

1;i>

0;i--

)return ans;

}int

main()

poj - 3252 round numbers

規定乙個數如果二進位制中0的個數大於等於1的個數,則這個數稱為「整數」,問閉區間a,b中有多少個整數。

題目分析:數字dp,dp[pos][c0][c1]代表前pos為中有c0個0和c1個1的整數數量

1、三維dp,範圍最大ll也就70,不慌

2、limit的判斷,可以用萬能的 limit&&i==a[pos]

#include

#pragma gcc optimize(2)

using

namespace std;

typedef

long

long ll;

const

int inf=

0x3f3f3f3f

;int dp[50]

[50][

50],a[35

],n,m,cnt;

intdfs

(int pos,

int c0,

int c1,

bool lead,

bool limit)if(

!limit&&

!lead&&dp[pos]

[c0]

[c1]!=-

1)return dp[pos]

[c0]

[c1]

;int mx=limit?a[pos]:1

;int ans=0;

for(

int i=

0;i<=mx;i++)if

(!limit&&

!lead&&dp[pos]

[c0]

[c1]==-

1) dp[pos]

[c0]

[c1]

=ans;

return ans;

}int

solve

(int x)

return

dfs(cnt-1,

0,0,

1,1)

;}intmain()

中等題hdu-3709 balanced number

題意:如果某個數可以從中選擇一位當作對稱點,然後左右兩邊的數字乘以該數字到對稱點的距離的和相等,那麼該數就被成為平衡數,比如4139,以3為對稱點,4 * 2 + 1 * 1=9 * 1。所以該數是平衡數。現在給你乙個區間,問該區間內有多少個平衡數。

1、三維,數字dp已經很常見了,用於問題拆分。

2、設變數有很多種,但得清晰

#include

#pragma gcc optimize(2)

using

namespace std;

typedef

long

long ll;

const

int inf=

0x3f3f3f3f

;ll dp[25]

[25][

500]

,a[25

],t,n,m,cnt;

//sum最大500>18*9

ll dfs

(int pos,

int mid,

int sum,

bool limit)

ll solve

(ll x)

ll ans=0;

for(

int i=

0;i) ans+

=dfs

(cnt-

1,i,0,

1);return ans-cnt+1;

//減去 0000 ,000 ,00這類多個0,但0是算的

}int

main()

}/*20 9

7604 24324

10897

*/

數字DP做題記錄

xdu1161 一本通1588 思路 用二維陣列dp i j 表示數字取到i位的情況下,各位數字之和對題中所給n取模為j的數字個數。例如對於樣例來說,dp 1 0 表示數字最多可取到1位,各個位之和對9取模為0個數字個數,這樣的數字有兩個,即0和9。類似地,dp 1 1 1,因為1 9 1 dp 1...

PAT甲級入門刷題記錄(一)

2020.1.15 2020.1.16 advance level 1001 a b format 題意 輸入兩個數進行加法,結果按照每三位乙個逗號進行標準輸出,資料量小,可以暴力,也可以使用邊計算邊輸出。1002 a b for polynomials 題意 兩個多項式相加。可以使用map 也可以...

OI刷題記錄

2014 4 18 poj3264 bzoj1699 balanced lineup rmq 2014 4 19 bzoj1012 jsoi2008 最大數maxnumber noi2004 鬱悶的出納員 bzoj3224 tyvj 1728 普通平衡樹 2014 4 20 bzoj1862 105...