loj6089 小 Y 的揹包計數問題

2022-05-07 20:42:09 字數 1300 閱讀 1155

link

好吧開學了果然忙得要死……不過為了證明我的blog還沒有涼,還是跑來更一波水題

有n種物品,第i種體積為i,問裝滿乙個大小為n的揹包有多少種方案?

$n\leq 10^5.$

這種題一看就很想按根號分類是不是……

設閾值大小為$m=\sqrt n$,對於體積$\leq m$的所有物品,直接跑多重揹包:

f[i][j]表示前i個物品,體積和為j的方案數,$f[i][j]=\sum f[i-1][j-ki],k\in [0,i]$。

記錄sum[x]表示$\sum f[i-1][j]$其中$j\% i=x$,同時需滿足當前的j和上乙個狀態lastj的差$\leq i^2$。這樣可以把dp優化到$\mathcal(n\sqrt n)$。

對於體積$>m$的所有物品,由於$i^2$一定$>n$,所以相當於完全揹包:

但是當然不能直接跑完全揹包,複雜度是炸的。可以發現物品的個數不超過$\sqrt n$,那麼

g[i][j]表示i個物品,體積和為j的方案數(注意和f的區別),$g[i][j]=g[i][j-i]+g[i-1][j-m-1]$。

具體來說這個轉移表示,要麼把當前i個物品每個體積都增加1,要麼插入乙個體積為m+1的物品(乙個構造法,恰好不重不漏地計算了所有方案)。

複雜度也是$\mathcal(n\sqrt n)$。

最後把兩者乘法原理合併起來即可。

題外話:51nod1259是一道類似的題,區別是它都是完全揹包,更簡單了些。

1 #include2

#define rep(i,x,y) for (int i=(x);i<=(y);i++)

3#define ll long long

4using

namespace

std;

5#define n 100005

6const

int mod=23333333;7

int n,m,f[2][n],sum[n],g[2

][n],now,t,ans;

8void upd(int &x,int y)

9int

main()17}

18 ans=f[now][n];t=now;

19 g[0][0]=1;now=0

;20 rep (i,1,m)

26 rep (i,0,n) upd(ans,(ll)f[t][i]*g[now][n-i]%mod);27}

28 cout<

29return0;

30 }

view code

LOJ6089 小 Y 的揹包計數問題

傳送門 to loj 不妨分成兩部分討論 x nx sqrt x和 x n x ge sqrt n x n 為啥要這麼分啊?這確實很難說。但是我們可以猜到,我們在讓這兩個值拿到平衡 值的種類和最多選取的個數。當值的種類很少時,直接多重揹包就行了。當選取的種類很少時呢?用 f x i f x,i f ...

loj6089 小Y的揹包計數問題

小 y 有乙個大小為 n 的揹包,並且小 y 有 n 種物品。對於第 i 種物品,共有 i 個可以使用,並且對於每乙個 i 物品,體積均為 i 求小 y 把該揹包裝滿的方案數為多少,答案對於 23333333 取模。定義兩種不同的方案為 當且僅當至少存在一種物品的使用數量不同。這個揹包問題讓我耳目一...

LOJ6089 小Y的揹包計數問題

小 y 有乙個大小為 n 的揹包,並且小 y 有 n 種物品。對於第 i 種物品,共有 i 個可以使用,並且對於每乙個 i 物品,體積均為 i 求小 y 把該揹包裝滿的方案數為多少,答案對於 23333333 取模。定義兩種不同的方案為 當且僅當至少存在一種物品的使用數量不同。第一行乙個整數 n 輸...