多项式练习题里面连续两道题都能打背包,当然不会去用多项式了。

decription

\(n\)个物品,完全背包(每个物品无限个),问你取恰好\(k\)个可以得到的体积有哪些。

solution

从背包的思路讲,取的个数只能用值表示,显然值表示的是取到对应体积的最小个数。
不过最少个数小于\(k\)也有可能恰好取到,但也不一定。
面对这种模棱两可的结果,如果存在一个值为\(0\)那就可以无限补零,这样就能用最少个数判断了。
不过还需要证明必要性:从构造的角度易证。
大概思想?删掉最小值,可多一个零,然后剩下做完全背包,最后背包加上最小值贡献。

easy code

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N];
int f[N],mn,mx;
int main() {
	int n,k;scanf("%d%d",&n,&k);
	mn=1e9;mx=-mn;
	for(int i=1;i<=n;i++) {scanf("%d",&a[i]);mn=min(mn,a[i]);mx=max(mx,a[i]);}
	for(int i=1;i<=n;i++) a[i]-=mn;
	int up=(mx-mn)*k;
	memset(f,0x3f,sizeof(f));f[0]=0;
	for(int i=1;i<=n;i++)for(int j=a[i];j<=up;j++)f[j]=min(f[j],f[j-a[i]]+1);
	for(int j=0;j<=up;j++) {if(f[j]<=k){printf("%d ",j+mn*k);}}
	return 0;
}