LOJ6089 小Y的揹包計數問題

2022-05-16 06:56:23 字數 1406 閱讀 7608

小 y 有乙個大小為 n 的揹包,並且小 y 有 n 種物品。

對於第 i 種物品,共有 i 個可以使用,並且對於每乙個 i 物品,體積均為 i 。

求小 y 把該揹包裝滿的方案數為多少,答案對於 23333333 取模。

定義兩種不同的方案為:當且僅當至少存在一種物品的使用數量不同。

第一行乙個整數 n 。

輸出一行,表示方案數。

n<=100000

觀察一下題目,最特殊的地方在於第 i 個物品只有 i 個。而揹包的容量只有 n ,所以,對於體積大於\(\sqrt\) 的物品,是不可能全部放完的。也就是說,\(\sqrt\)以後的物品相當與沒有限制存在。所以,初步的思路是小於\(\sqrt\) 的物品用多重揹包,大於的用完全揹包。

但是即使這樣也無法通過。我們需要優化兩種dp。

先來考慮多重揹包。設\(f[i][j]\)表示前\(i\)個物品消耗了\(j\)的體積,那麼多重揹包的轉移方程是這樣的:

\[f[i][j]=\sum_^f[i-1][j-k \times i]

\]可以發現,\(f[i][j]\)只會從\(f[i-1][j],f[i-1][j-i],...,f[i-1][j-k\times i]\)轉移過來。所以,我們可以用類似字首和的方式優化轉移,將前半部分的複雜度優化到\(o(n\sqrt)\)。

再來考慮完全揹包。我們可以轉化一下模型。假設我們現在有很多長度為\(\sqrt\)的木棍,每次可以在最前面加入一根,或者把所有已經加入的木棍的長度全部加一。設\(g[i][j]\) 表示選了\(i\)根木棍,總長度為\(j\)的方案數,那麼,我們有如下dp方程:

\[g[i][j]=g[i-1][j-\sqrt]+g[i][j-i]

\]其實,\(g[i][j]\)對應的就是原問題中選了前\(i\)個物品,總體積為\(j\)的方案數。有了這些,我們就可以統計答案了。設\(sum[i]=\sum_+1}^ g[j][i]\) ,那麼答案就是

\[ans=\sum_^f[\sqrt][i]\times sum[n-i]

\]

#include #include #include #define n 100002

#define m 350

using namespace std;

const int mod=23333333;

int n,m,f[m][n],g[m][n],sumf[n],sumg[n],i,j,k,l;

int read()

return w;

}signed main()

} long long ans=0;

for(i=0;i<=n;i++) ans=(ans+1ll*f[m][i]*sumg[n-i]%mod)%mod;

printf("%lld\n",ans);

return 0;

}

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 的揹包計數問題

link 好吧開學了果然忙得要死 不過為了證明我的blog還沒有涼,還是跑來更一波水題 有n種物品,第i種體積為i,問裝滿乙個大小為n的揹包有多少種方案?n leq 10 5.這種題一看就很想按根號分類是不是 設閾值大小為 m sqrt n 對於體積 leq m 的所有物品,直接跑多重揹包 f i ...

loj6089 小Y的揹包計數問題

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