noip 2018 货币系统 完全背包
如果一个数能被比它小的数表示出来,那么这个数就不用选
跑一遍完全背包即可
#include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; int arr[1000],f[100000],A[100000],bomb[100000]; void setIO(string a){ freopen((a+".in").c_str(),"r",stdin); freopen((a+".out").c_str(),"w",stdout); } int main(){ //setIO("money"); int T; scanf("%d",&T); while(T--){ memset(f,0,sizeof(f)); memset(bomb,0,sizeof(bomb)); memset(arr,0,sizeof(arr)); memset(A,0,sizeof(A)); int n,flag=0,maxv=0,cnt=0; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&arr[i]); maxv=max(maxv,arr[i]); if(!bomb[arr[i]]) { bomb[arr[i]]=1; A[++cnt]=arr[i];} if(arr[i]==1) flag=1; } if(flag==1) { printf("1\n"); continue; } f[0]=1; for(int i=1;i<=cnt;++i){ for(int j=A[i];j<=maxv;++j) f[j]+=f[j-A[i]]; } for(int i=1;i<=maxv;++i) if(bomb[i] && f[i]!=1) --cnt; printf("%d\n",cnt); } return 0; }