傳送門
完了我連揹包都不會了……
考慮暴力,先列舉最小的數是哪個,設大小為$d_i$,個數為$k_i$,所有比它小的數的總和是$sum$,然後把所有比它小的全都裝進揹包,它以及比他大的做乙個多重揹包,那麼設$dp[j]$表示在剩下的這些數里取的總和為$j$時的方案數,那麼$$ans+=\sum_^ dp[j]$$
上面的式子意思就是,將所有比它小的全放進去之後,列舉揹包剩餘的空間,統計所有方案數。因為不能讓把任何大於等於它的在統計之前就放進去,所以下界是$m-sum-d_i+1$
然後現在的問題就是怎麼統計了才能過。我們可以從大到小列舉,這樣的話每做到乙個物品就只需要對它自己做多重揹包,不需要重新dp了
接下來的操作真的是學到了……在做多重揹包的時候把$j$按照模$d_i$的取值分為不同的組,然後時間複雜度就能優化到$o(nm)$
簡單來講的話,就是轉移的時候$dp[j]+=dp[j-d_i]+dp[j-d_i*2]...+dp[j-d_i*k_i]$,發現每乙個$j$只會被與它模$d_i$同餘的轉移到,於是我們列舉這乙個餘數,統計與它同餘的數的字首和,然後從小到大轉移並不斷維護字首和即可(真的很妙)
1//minamoto
2 #include3 #include4 #include5
using
namespace
std;
6#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?eof:*p1++)
7char buf[1
<<21],*p1=buf,*p2=buf;
8int
read()
18const
int n=505,m=1e5+5,mod=19260817;19
struct
node
22}a[n];
23int n,m,ans,tot,dp[2
][m],t;
24 inline int add(int x,int y)
25 inline int del(int x,int y)
26void ins(int k,int
w)35}36
}37intmain()
50 printf("
%d\n
",ans);
51return0;
52 }
luogu4241 採摘毒瘤 題解
題意分析 給出 n 種物品,每種物品有數量和大小,要求放入一定大小的揹包,求不能再放入任何物品的方案數。思路分析 分析後可以發現這個問題就是在多重揹包計數問題的基礎上加上了放不進剩下的物品的條件,考慮對這個條件進行處理。可以想到列舉剩下的物品中體積最小的物品,然後將比它小的物品先放進去,再對剩下的物...
洛谷 P1086 花生採摘
題目描述 魯賓遜先生和多多都很開心,因為花生正是他們的最愛。在告示牌背後,路邊真的有一塊花生田,花生植株整齊地排列成矩形網格 如圖1 有經驗的多多一眼就能看出,每棵花生植株下的花生有多少。為了訓練多多的算術,魯賓遜先生說 你先找出花生最多的植株,去採摘它的花生 然後再找出剩下的植株裡花生最多的,去採...
洛谷 P1086 花生採摘
魯賓遜先生有乙隻寵物猴,名叫多多。這天,他們兩個正沿著鄉間小路散步,突然發現路邊的告示牌上貼著一張小小的紙條 歡迎免費品嚐我種的花生!熊字 魯賓遜先生和多多都很開心,因為花生正是他們的最愛。在告示牌背後,路邊真的有一塊花生田,花生植株整齊地排列成矩形網格 如圖1 有經驗的多多一眼就能看出,每棵花生植...