Description
给出一个天平和 n n 个砝码,第个砝码的质量为 ai a i ,问 [1,S] [ 1 , S ] 有哪些质量称不出来,其中 S S 为砝码总质量
Input
多组用例,每组用例第一行首先输入一整数表示砝码个数,之后输入 n n 个整数表示砝码质量 (1≤n,ai≤100) ( 1 ≤ n , a i ≤ 100 )
Output
输出不能称出来的质量数以及这些质量
Sample Input
3
1 2 4
3
9 2 1
Sample Output
0
2
4 5
Solution
砝码可放左边也可放右边也可不放,故 i i 砝码对天平两端质量差贡献的生成函数为
令 F(x)=∏i=1nPi(x) F ( x ) = ∏ i = 1 n P i ( x ) 表示天平两端质量差的生成函数,对于 j∈[1,S] j ∈ [ 1 , S ] ,如果 [xj]F(x)≠0 [ x j ] F ( x ) ≠ 0 或 [x−j]F(x)≠0 [ x − j ] F ( x ) ≠ 0 说明天平可以称出来 j j 质量,否则不行,暴力计算得到即可
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;
}