time limit per test5 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
A thief made his way to a shop.
The first line contains two integers n and k (1 ≤ n, k ≤ 1000) — the number of kinds of products and the number of products the thief will take.
The second line contains n integers ai (1 ≤ ai ≤ 1000) — the costs of products for kinds from 1 to n.
Print the only line with all the possible total costs of stolen products, separated by a space. The numbers should be printed in the ascending order.
3 2
1 2 3
2 3 4 5 6
5 5
1 1 1 1 1
5
3 3
3 5 11
9 11 13 15 17 19 21 25 27 33
题意
有n个数,然后这n个数里面选k个加起来
问你一共能加出来多少种
题解:
多项式加法,加k次,问你最后的数是哪些。
DP。dp[i]表示最少用多少个非a[1]能够构成a[1]*k+i的。
#include<bits/stdc++.h>
using namespace std;
int a[1010], dp[1000005], done[1010]={0};
int main()
{
int mod = 1e9;
fill( dp + 1, dp + 1000001 , mod);
int n ,k, mn = mod, mx = 0;
cin >> n >> k;
for(int i=1;i<=n;++i)
{
cin >> a[i];
mn = min( mn , a[i]);
mx = max( mx , a[i]);
}
for(int i=1;i<=n;++i)
a[i] -= mn;
int t = 0;
for(int i=1;i<=n;++i)
if( a[i] != 0)
a[++t] = a[i];
n = t;
dp[0]=0;
for(int i = 1; i <= n;++i){
if( done[a[i]])
continue;
done[a[i]] = 1;
for(int j = 1; j<=mx*k;++j){
if(j>=a[i])
if(dp[j] > dp[j-a[i]] + 1)
dp[j] = dp[j-a[i]] + 1;
}
}
for(int i = 0; i <= mx * k; ++i)
if( dp[i] <= k)
printf("%d ",mn * k + i);
return 0;
}