题目链接:http://noip.ybtoj.com.cn/contest/50/problem/2
分析
把货币系统 ( n , a ) (n,a) (n,a)看做集合A, ( m , b ) (m,b) (m,b)看做集合B,那么A集合不能表示出来的数必然在B集合内。
考虑完全背包,从小到大排序,看看能否被之前的数表示出来。
其实最新的等价最小系统就是原来的数量减去所有能被原系统内的数表示出来的数。例如:6=3+3,19=10+3+3+3。
转移方程: f [ j ] = f [ j ] ∣ ( f [ j − a [ i ] ] ) f[j]=f[j]|(f[j-a[i]]) f[j]=f[j]∣(f[j−a[i]])
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int t,n,a[100001],f[100001];
int main()
{
cin>>t;
while(t--)
{
memset(f,0,sizeof(f));
cin>>n;
int ans=n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
f[0]=1;
for(int i=1;i<=n;i++)
{
if(f[a[i]])
{
ans--;
continue;
}
for(int j=a[i];j<=a[n];j++)
{
f[j]=f[j]|(f[j-a[i]]);
}
}
cout<<ans<<endl;
}
return 0;
}