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;
    
}
View Code

 

posted @ 2020-06-24 15:18  汉谡  阅读(124)  评论(0编辑  收藏  举报