T137226 彩虹海
设目标体系$(n,a)$和答案体系$(m,b)$分别为集合$A$和集合$B$,那么我们可以猜想$B\subseteq A$。
我们可以先通过反证法验证下面两个结论:
若$x\in A$可以被其他$A$中的数表达出来,那么有$x\notin B$。
若$x\in A$不能被其他$A$中的数表达出来,那么有$x\in B$。
然后再通过上述结论,使用反证法证明$B\subseteq A$。具体就是取一个$x$,令$x\in B$且$x\notin A$,证明这样的$x$不存在。
于是我们只需要找到$A$中能被表达出来的数并删去即可。
具体来说,需要先将$a$排序,然后每次$\forall x\in[a_i,a_n]$,令$f_x\leftarrow f_{x-a_i}$。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define IL inline #define RG register using namespace std; #define RI RG int #define RC RG char const int N=100; const int M=25000; int T,n,a[N+3]; bool f[M+3]; IL void sol(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); memset(f,0,sizeof(f)); f[0]=1; int ans=n; for(RI i=1;i<=n;i++){ if(f[a[i]]){ ans--; continue; } for(int j=a[i];j<=a[n];j++) f[j]|=f[j-a[i]]; } printf("%d\n",ans); } int main(){ freopen("data.in","r",stdin); freopen("data.ans","w",stdout); scanf("%d",&T); while(T--) sol(); return 0; }