題解 51nod 1597 有限揹包計數問題

2022-05-01 19:27:09 字數 1194 閱讀 2477

題目傳送門

給出 \(n\),第 \(i\) 個數有 \(i\) 個,問湊出 \(n\) 的方案數。

\(n\le 10^5\)

嗚嗚嗚,傻掉了。。。

首先想到根號分治,分別考慮 \([1,\sqrt n]\) 以及 \([\sqrt n+1,n]\)。

\([1,\sqrt n]\)

不難看出這部分可以直接 dp,設 \(f_\) 為前面 \(i\) 種物品選出重量為 \(j\) 的方案數,可以得到轉移式:

\[f_=f_+f_-f_

\]\([\sqrt n+1,n]\)

不難看出這部分最多選出 \(\sqrt n\) 個物品,於是可以設 \(g_\) 表示選了 \(i\)物品,選出重量為 \(j\) 的方案數。可以得到轉移式:

\[g_=g_+g_

\]具體含義就是轉移有兩種,第一種就是集體右移,即重量為 \(k\) 的都變為 \(k+1\),另外一種就是選 \(\sqrt n+1\)。

綜上時空複雜度 \(\theta(n\log n)\),第一種記得滾動陣列,不然會 mle。

#include using namespace std;

#define int register int

#define mod 23333333

#define maxn 100005

#define maxm 325

template void read (t &x)

template void read (t &x,args& ... args)

template void write (t x)

int n,sqr;

int f[2][maxn],g[maxm][maxn],f1[maxn],f2[maxn];

/*f[i][j] 表示前面i個物品選出重量j的方案數,g[i][j]表示i個物品選出重量j的方案數

f[i][j]=f[i-1][j]+f[i][j-i]-f[i-1][j-i*(i+1)]

g[i][j]=g[i][j-i]+g[i-1][j-sqr-1]

*/int dec (int a,int b)

int add (int a,int b)

void work1 ()

void work2 ()

signed main()

51nod1597 有限揹包計數問題

你有乙個大小為n的揹包,你有n種物品,第i種物品的大小為i,且有i個,求裝滿這個揹包的方案數有多少 兩種方案不同當且僅當存在至少乙個數i滿足第i種物品使用的數量不同 n 100000,答案模23333333,時限2.333s 這道題一看是一道多重揹包,但是範圍有點大啊。可以嘗試利用一下題目的條件,對...

51nod1597 有限揹包計數問題

51nod1597 有限揹包計數問題 試題描述 你有乙個大小為n的揹包,你有n種物品,第i種物品的大小為i,且有i個,求裝滿這個揹包的方案數有多少 兩種方案不同當且僅當存在至少乙個數i滿足第i種物品使用的數量不同 輸入 第一行乙個正整數n 1 n 10 5 輸出 乙個非負整數表示答案,你需要將答案對...

51Nod 1597 有限揹包計數問題

首先這是乙個多重揹包 但是它的資料非常特殊,我們可以利用其性質優化演算法 乙個顯然的優化是 當 i sqrt n 時,可以取消個數限制 設 f i j 表示選了 i 個物品,體積為 j 的方案數 一共有兩種轉移 可以由 i 1 個物品加上乙個最小的物品 sqrt n 1 可以由 i 個物品全部加一 ...