Description
给出一个天平和nn个砝码,第个砝码的质量为aiai,问[1,S][1,S]有哪些质量称不出来,其中SS为砝码总质量
Input
多组用例,每组用例第一行首先输入一整数表示砝码个数,之后输入nn个整数表示砝码质量(1≤n,ai≤100)(1≤n,ai≤100)
Output
输出不能称出来的质量数以及这些质量
Sample Input
3
1 2 4
3
9 2 1
Sample Output
0
2
4 5
Solution
砝码可放左边也可放右边也可不放,故ii砝码对天平两端质量差贡献的生成函数为
令F(x)=∏i=1nPi(x)F(x)=∏i=1nPi(x)表示天平两端质量差的生成函数,对于j∈[1,S]j∈[1,S],如果[xj]F(x)≠0[xj]F(x)≠0或[x−j]F(x)≠0[x−j]F(x)≠0说明天平可以称出来jj质量,否则不行,暴力计算得到即可
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=10005;
int n,v[maxn],a[maxn],b[maxn];
int main()
{
while(~scanf("%d",&n))
{
int m=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
m+=v[i];
}
for(int i=0;i<=m;i++)a[i]=0;
a[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
for(int k=0;k<=v[i];k+=v[i])
b[j+k]|=a[j],b[abs(j-k)]|=a[j];
for(int j=0;j<=m;j++)a[j]=b[j],b[j]=0;
}
int res=0;
for(int i=1;i<=m;i++)res+=!a[i];
printf("%d\n",res);
for(int i=1;i<=m;i++)
if(!a[i])
{
res--;
printf("%d%c",i,res?' ':'\n');
}
}
return 0;
}