鏈結
題意:給出a、b、c,求 x&y
>
cx \& y > c
x&y>c或x
y<
cx ^ y < c
xy<
c的(x,y)對數(1
<=x
<=a
,1
<=y
<=b
1<=x<=a,1<=y<=b
1<=x
<=a
,1<=y
<=b
)思路:
一開始不知道怎麼做,以前只做過乙個數的數字dp,沒想到兩個數也可以做。
正著想的話就會有三種情況,倒著想的話只要總的減去x&yc就好了。
定義d p[
pos]
[lim
a][l
imb]
[and
][xo
r][z
a][z
b]
dp[pos][lima][limb][and][xor][za][zb]
dp[pos
][li
ma][
limb
][an
d][x
or][
za][
zb]pos:當前到第幾位
lima:數字x是否達到上限
limb:數字y是否達到上限
and:x和y與運算是否小於c
xor:x和y亦或運算是否大於c
za:x是否出現過非0的數字
zb:y是否出現過非0的數字
從高位列舉,如果之前x和y相與已經小於c了,那麼後面都會小於c。同樣如果之前x和y亦或已經大於c了,那麼之後都會一直大於c。注意x和y中有乙個是全0都是不合法的情況。
最後a*b減去數字dp求出來的值就是最後的答案了。
#include
using
namespace std;
typedef
long
long ll;
const ll maxn =50;
bool a[maxn]
;bool b[maxn]
;bool c[maxn]
;ll dp[50]
[2][
2][2
][2]
[2][
2];ll dfs
(int pos,
bool lima,
bool limb,
bool ad,
bool xr,
bool za,
bool zb)
if(dp[pos]
[lima]
[limb]
[ad]
[xr]
[za]
[zb]!=-
1)return dp[pos]
[lima]
[limb]
[ad]
[xr]
[za]
[zb]
;int topa=lima?a[pos]:1
;int topb=limb?b[pos]:1
; ll tmp=0;
for(
int i=
0;i<=topa;i++)}
return dp[pos]
[lima]
[limb]
[ad]
[xr]
[za]
[zb]
=tmp;
}int
main()
for(
int i=
0;i<=
30;i++
)for
(int i=
0;i<=
30;i++
)printf
("%lld\n"
,ans-
dfs(30,
true
,true
,false
,false
,false
,false))
;}return0;
}
H pair 2019牛客多校第七場
傳送門 這題一直忘了補。今天沒比賽剛好補了 比賽的時候看見以為是撒高階數論計數題,然而怎麼過了這麼多人,最後沒想到是數字dp。我們知道對於位運算來說,當高位 c 或者 高位 所以從高位開始數字dp dp pos dc xc sta stb az bz 表示從最高位到pos 1位所有列舉的情況 的 值...
2019牛客多校第七場H Pair 數字DP
題意 給你乙個3個數a,b,c問有多少對pair i,j 1 i a,1 j b,i and j c或 i xor j c。a,b,c範圍為1e9.思路 場上一看以為是推式子加什麼篩做,無果。之後才知道是數字dp 以下思路來自學長的 orz 首先,我們可以把問題轉化為求i and j c並且 i x...
2018牛客多校7
有點難度啊。a minimum cost perfect matching 隊友搞的 應該不難 把二進位制寫出來看看 includeusing namespace std define ll long long int define lson rt 1,l,m define rson rt 1 1,...