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