題目傳送門
給出 \(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 個物品全部加一 ...