意思就是给定一个包含n个元素的集合A,求一个最小的子集B使得A能表示的数B也能表示,A不能表示的数B也不能表示。
我们可以发现,因为B是A的子集,所以A不能表示的数B一定不能表示,因此我们只需要处理能表示的数就可以。
再仔细想一下,其实这道题就是让我们求这个集合里哪些元素不可以被集合里的其他元素表示,比如样例的集合{3,19,10,6},如果一个元素可以被其他元素代替,那么这个元素可以表示的不属于这个集合的元素也可以被表示出来,比如12=6+6,而6=3+3,所以我们没必要保留6,想通以后就很容易发现这是一道完全背包求方案数的题,只不过需要先从小到大排序一遍。
AC代码:
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#include <algorithm>
#include<string.h>
#include<math.h>
#define llu unsigned long long
using namespace std;
int main()
{
int t;
cin >> t;
while(t--)
{
bool vis[99999]={0};
int n;
cin >> n ;
int a[n+10];
for(int i=0;i<n;i++)
{
cin >> a[i];
}
sort(a,a+n);
int ans=0;
vis[0]=1;
for(int i=0;i<n;i++)
{
if(!vis[a[i]])
{
ans++;
for(int j=0;j<=a[n-1]-a[i];j++)
{
if(vis[j]) vis[j+a[i]]=1;
//cout << j+a[i] << " " << vis[j+a[i]] << endl ;
//cout << ans << endl ;
}
}
}
cout << ans << endl ;
}
return 0;
}