51Nod 1597 有限揹包計數問題

2022-05-16 10:25:57 字數 1446 閱讀 2645

首先這是乙個多重揹包

但是它的資料非常特殊,我們可以利用其性質優化演算法

乙個顯然的優化是

當\(i>\sqrt n\)時,可以取消個數限制

設\(f[i][j]\)表示選了\(i\)個物品,體積為\(j\)的方案數

一共有兩種轉移

可以由\(i-1\)個物品加上乙個最小的物品\(\sqrt n+1\)

可以由\(i\)個物品全部加一(全部換成下乙個)

即\(f[i][j]=f[i-1][j-(\sqrt n+1)]+f[i][j-i]\)

考慮得到乙個答案的過程

對於每乙個過程都會得到乙個合法的答案

對於每乙個合法的答案都有唯一乙個過程

因為對於每乙個方案

如果其中存在最小的物品

那麼一定是由第一種方案轉移

否則一定是由第二種方案轉移

比如\(n=16\)

體積為\(16\)的一種方案是\(5+5+6\)

這個狀態一定由\(5+6\)轉移來

因為\(4=\sqrt 16\),比最小的物品還小

所以\(4+4+5\)是不可能的

體積為\(12\)的一種方案是\(6+6\)

這個狀態一定由\(5+5\)轉移來

因為方案裡並沒有\(5\)(最小的物品)

所以方案與過程一一對應

複雜度\(o(n\sqrt n)\)

剩下的是多重揹包

\(f[i][j]=\sum_^\)

按模\(i\)分類

複雜度\(o(n\sqrt n)\)

最後列舉多少空間給前\(\sqrt n\)個物品(剩下空間給其它物品)

統計答案即可

複雜度\(o(n\sqrt n)\)

#includeusing namespace std;

#define gc c=getchar()

#define r(x) read(x)

templateinline void read(t&x)

while(isdigit(c))x*=k;

}const int p=23333333;

const int n=1e5+7;

int sum[n],f1[2][n],f2[2][n];

inline int add(int a,int b)

int main()

memset(sum,0,i<<2); }

memset(sum,0,(n+1)<<2);

f2[0][0]=1;

for(int i=1;i<=t;++i) }

sum[0]=1;

long long ans=0;

for(int i=0;i<=n;++i)(ans+=1ll*f1[t&1][i]*sum[n-i])%=p;

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

}

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 有限揹包計數問題 dp

你有乙個大小為n的揹包,你有n種物品,第i種物品的大小為i,且有i個,求裝滿這個揹包的方案數有多少 兩種方案不同當且僅當存在至少乙個數i滿足第i種物品使用的數量不同 1 n 10 5,答案對23333333取模 設lim sqrt n 我們把所有物品按照大於lim和不大於lim分成兩部分。對於大於l...