分組揹包 牛客練習賽22C bitset優化

2021-10-07 01:13:50 字數 1733 閱讀 2795

link

一共有 n個數,第 i 個數是 x

ix_i

xi​ ,x

ix_i

xi​ 可以取 [li

,ri]

[l_i , r_i]

[li​,r

i​] 中任意的乙個值。

設 s =∑

xi

2s = \sum^2}

s=∑xi​

2, 求 s 種類數。

這一題主要用的是分類揹包的思想,dp[

i][j

]dp[i][j]

dp[i][

j]表示的是考慮到第i

ii個區間,s是否能取到j

jj,取到為1,取不到為0。

進行三重迴圈遍歷(第一層區間數n

nn,第二層j

jj的取值可以到達n

3n^3

n3,第三層為區間中的每個數遍歷為n

nn),總複雜度到達了o(n

5)

o(n^5)

o(n5)。

這樣進行動態規劃的話比較浪費時間和記憶體,因為每個狀態只有01兩種取值,因此可以用 bitset 進行優化, 將1in

t1 \ int

1int

壓成1 bi

t1 \ bit

1bit

。bitset的基本用法:link (bitset可以進行各種位操作,以及cou

nt,s

et

count,set

count,

set方法的使用)

可以d p[

i]

dp[i]

dp[i

]表示第i

ii個區間可以表示的s(s的最大取值為106

10^6

106,因此bitset最多需要106

10^6

106位), 對於區間中的每個數j

jj,可以得出這樣的轉移方程dp[

i]∣=

dp[i

−1

]<

<(j

∗j

)dp[i] \ |= \ dp[i-1]<<(j*j)

dp[i]∣

=dp[

i−1]

<

<(j

∗j), 這樣複雜度降到了 o(n

/32

)o(n/32)

o(n/32

), 並且其中的位操作是更快的。

最後答案即為dp[

n]

dp[n]

dp[n

]中1的個數,可以用cou

nt()

count()

count(

)方法得到。

#include

using

namespace std;

typedef

long

long ll;

const

int maxn =

1e6+10;

const

int inf =

0x3f3f3f3f

;bitset dp[

102]

;int n, l ,r;

intmain()

printf

("%d\n"

, dp[n]

.count()

);}

牛客練習賽22題解

簡單瞎搞題 不會用bitset,所以沒做出來。實際上還是比較簡單的。include using namespace std bitset 1000005 dp 2 int main cout 2 count 簡單資料結構1 這裡要運用拓展尤拉定理。ab modp ab p b p p 0 modp ...

牛客練習賽 22 A

給6個火柴棍,問能不能拼成 熊 或者 象 熊 4根棍子長度一樣,另外2根棍子長度不一樣 象 4根棍子長度一樣,另外2根棍子長度一樣。如果可以拼出熊,輸出 bear 如果可以拼出象,輸出 elephant 如果都不可以拼出,輸出 hernia 一行六個數表示每個火柴棍的長度輸出一行乙個字串表示答案示例...

牛客練習賽 22 c bitset

一共有 n個數,第 i 個數是 xix i可以取 l i r i 中任意的乙個值。設第一行乙個數 n。然後 n 行,每行兩個數表示 li ri。輸出一行乙個數表示答案。include bits stdc h define maxx 1000009 using namespace std bitset...