这题我们要这么考虑:

如果一种货币可以被另外的一种或多种货币表示的话,那么这种货币明显就是不必要的。

而答案,明显就是所有必要货币的个数。

那么,我们来考虑下怎么做。

首先,很容易发现的是,面值最小的货币一定是必要的,因为它不可能被其它货币表示。

然后,我们再同样的,看面值次小的,这时,我们有两种情况:

1.次小的可以被最小的表示,即次小的是最小的倍数。那么次小的就是不必要

2.次小的不能被最小的表示,那么明显,它也就不能被其它的货币表示了,所以它就是必要

那么,我们就可以按这个思路依次推导下去。。。

我们设dp[i]表示面值i能否被当前的已选择的必要货币表示

我们先将所有货币的面值由小到大排个序,然后,每次,我们看看当前的货币能否被之前的货币表示,若能,那么这个货币就是不必要的,我们不管它。若不能,则这个货币就是必要的,那么,我们把它添加进我们的货币系统中,并同时更新dp数组,就行了。

考场代码:

#include<bits/stdc++.h>
using namespace std;
const int N=3e4+1,M=101;
int a[M],e;
bool vis[N];
int main(){
//    freopen("money.in","r",stdin);
//    freopen("money.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1);
        memset(vis,0,sizeof(vis));
        e=0;
        e++;
        vis[a[1]]=1;
        for(int i=2;i<=a[n]/a[1];++i){
            vis[i*a[1]]=1;
        }
        for(int i=2;i<=n;++i){
            if(vis[a[i]]){
                continue;
            }
            e++;
            vis[a[i]]=1;
            for(int j=a[i]+1;j<=a[n];++j){
                if(!vis[j]&&vis[j-a[i]]){
                    vis[j]=1;
                }
            }
        }
        printf("%d\n",e);
    }
    return 0;
}