51nod1597 DP 有限揹包計數問題

2021-07-24 01:16:32 字數 1830 閱讀 6141

你有乙個大小為n的揹包,你有n種物品,第i種物品的大小為i,且有i個,求裝滿這個揹包的方案數有多少

兩種方案不同當且僅當存在至少乙個數i滿足第i種物品使用的數量不同

第一行乙個正整數n

1<=n<=10^5

乙個非負整數表示答案,你需要將答案對23333333取模

dp,一開始沒什麼思路,然後研究了很久終於會做了,感覺我dp超弱

先是分成兩部分,大於n√

和小於n√

的,小於的部分是有限制的揹包,大於的部分是完全揹包(因為你用不完),我們就可以分成兩部分dp,兩部分都不難,但是滾動再加上字首和我就懵逼了,前面就是字首和加滾動,後面是個序列dp。

前面dp[i][j]表示前i個數,體積為j,然後對於同乙個i就是加上它的字首和,然後滾一下i就好了

後面可以分為兩種操作,乙個是加乙個m+1這個數,乙個所有數加一

然後再乘法原理就好了

但是完全不知道為什麼我原先寫那個(注釋裡面的)在本機上測全部過,但是交上去就各種wa,樣例都要wa,完全不知道為什麼,是不是什麼編譯器的問題

然後下面是我的**,注釋掉的是我原來寫的,注釋後面的是網上抄的,完全不知道為什麼我的交上去要wa

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define inf 2100000000

#define ll long long

#define clr(x) memset(x,0,sizeof(x))

#define maxclr(x) memset(x,127,sizeof(x))

#define n 320

#define m 100005

#define p 23333333ll

using

namespace

std;

int dp[2][m],tmp[m],g[n][m],n,m,ans;

ll g1[m],f1[m];

int now,pre;

int main()

if(i&&j>=i)g[i][j]=(g[i][j]+g[i][j-i])%p;

if(j>m)g[i][j]=(g[i][j]+g[i-1][j-m-1])%p;}}

/*

for(int i=0;i<=m;i++)

for(int j=0;j<=n;j++)

ans=((ll)ans+(ll)dp[now][j]*(ll)g[i][n-j])%p;

*/++g1[0];

for (int i=1;i<=n;++i)

for (int j=1;j<=m;++j)

(g1[i]+=g[j][i])%=p;

for (int i=0;i<=n;++i)f1[i]=dp[now][i];

for (int i=0;i<=n;++i)

(ans+=(f1[i]*g1[n-i]%p))%=p;

cout

<'\n';

return

0;}

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

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

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 輸出 乙個非負整數表示答案,你需要將答案對...