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 #include2view code#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 }
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 輸...