noip2018 洛谷 P5020 货币系统
关键: 要使m最小,(m,b)中的数不能用(n,a)中的数表示出来
对于 3 19 10 6
19=10+3+3+3
6=3+3
只有3 和 10 不能被(n,a)中的数表示
所以m=2
只需要计算出存在多少个能被其它数组成的数计算出来就行了。
法一:完全背包
一个数只能被比它小的数字组成而不能被比它大的数字组成。
可以首先对数组排序,然后对于每一个数考虑能不能被它前面的数字所组成。
若x能够被前i个数组成,那么x-a[i]也能被前i个数组成
f[x]表示x能否被组成
则f [ x ] = f [ x ] | f [ x - a [ i ] ]
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=25000; 4 int main() 5 { 6 int a[maxn]; 7 int f[maxn]; 8 int t,n; 9 int ans; 10 cin>>t; 11 while(t--){ 12 memset(f,0,sizeof(f)); 13 cin>>n; 14 ans=n; 15 for(int i=1;i<=n;i++) 16 cin>>a[i]; 17 sort(a+1,a+n+1); 18 f[0]=1; //边界 19 for(int i=1;i<=n;i++) 20 { 21 if(f[a[i]])//a[i]能被前面的数表示 22 { 23 ans--; 24 continue; 25 } 26 for(int j=a[i];j<=a[n];j++) 27 f[j]= (f[j]) | (f[j-a[i]]); 28 } 29 cout<<ans<<endl; 30 } 31 return 0; 32 }