數字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...