题意:全集A为n个a[i],若有某个集合B其和为k,则B的任意一个子集C定义其元素之和x为合法
n,k,c[i]<=500 求出所有合法的x.
设dp[i][j][k] 表示前i个数能凑出子集和为j,和为j的集合又有子集和为k
n,k,c[i]<=500 求出所有合法的x.
设dp[i][j][k] 表示前i个数能凑出子集和为j,和为j的集合又有子集和为k
考虑第i个数是否加入,加入到集合j时,又分是否加入集合j的子集.
dp[i][j][k]|=dp[i-1][j][k]|dp[i-1][j-a[i][k]|dp[i-1][j-a[i]][k-a[i]].
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e2+1;
int dp[N][N],a[N],n,K;
vector<int> ans;
int main()
{
while(cin>>n>>K)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=500;j>=0;j--)
{
for(int k=500;k>=0;k--)
{
dp[j][k]|=dp[j][k];
if(j>=a[i])
dp[j][k]|=dp[j-a[i]][k];
if(j>=a[i]&&k>=a[i])
dp[j][k]|=dp[j-a[i]][k-a[i]];
}
}
}
for(int i=0;i<=K;i++)
{
if(dp[K][i])
ans.push_back(i);
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}