在Acwing这样大佬众多的网站上发布题解,心里很激动!
一个对于此题的结论:货币系统$(m,b)$中的元素全部来自货币系统$(n,a)$
由于本人菜的可怜,数学知识很少,请允许我用一种思维理解的方式来想。
如果存在一个$x$,它存在于新的货币系统中但是不存在原来的货币系统中,根据题意,$x$必须能用原来的货币系统表示出来。那么表示它的这些数肯定在新的货币系统中。既然如此,x就没有必要存在了。(题目要求新货币系统中元素个数尽可能小)
新的货币系统长什么样子??
在$(n,a)$这个货币系统中,可能存在一些面额,这些面额能被其他面额相加所得(以我们的毛爷爷举例子,该货币系统是$(1,5,10,20,50,100)$【只考虑元】,我们发现事实上我们只需要1元的货币就可以把其他的面额表现出来)那么在新的货币系统中我们就也不需要这些面额了。
我们用$f[i]$表示该为$i$是否在于新货币系统中
具体解释请看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,n,a[25010];
int f[25010];
int main(){
cin>>T;
for(int k = 1 ; k <= T ; k ++){//一共有T组数据
int ans = 0;
memset(f,0,sizeof(f));//每次都要把ans和f初始化一下~~
cin>>n;
for(int i = 1 ; i <= n ; i ++)cin>>a[i];
sort(a+1,a+1+n);//从小到大排序,方便之后的去重
f[0] = 1;//一定要把这个设为1,否则后边的去重全乱了
for(int i = 1 ; i <= n ; i ++){
if(!f[a[i]]){//如果这个面额不能被标示(因为我们是从小到大搜,所以一旦搜到说明这个面额应该存在)
ans++;
f[a[i]]=1;//标记这个面额可以被标示
for(int j = a[i] ; j <=a[n] ; j ++){//从当前面额到最大面额,比他小的面额已经搜过了
if(f[j-a[i]])f[j] = 1;//如果j-当前面额 可以被表示,说明j也可以被表示出来
}
}
}
cout<<ans<<endl;
}
return 0;
}
//如果j-当前面额 可以被表示,说明j也可以被表示出来 这句话让我看懂了 找了好多篇题解了 一直没弄明白这里的意思