思路
因为题目想让m最小,那首先得符合题目的等价条件;
当 m = n 当m=n 当m=n, a [ i ] = b [ i ] 时 a[i]=b[i]时 a[i]=b[i]时,必然可以;
接着我们想缩小这个m;
怎么缩小呢?
- 如果存在某个 a [ i ] a[i] a[i]能被其他的 a [ i ] a[i] a[i]表示,那么这个 a [ i ] a[i] a[i]就是多余的
- 我们对 a [ i ] a[i] a[i]排序,因为大的 a [ i ] a[i] a[i]肯定可以从小的 a [ i ] a[i] a[i]转移过来
- 利用完全背包, f [ i ] [ j ] 表 示 前 i 个 数 , 总 和 为 j 的 时 候 能 否 被 表 示 f[i][j]表示前i个数,总和为j的时候能否被表示 f[i][j]表示前i个数,总和为j的时候能否被表示
Code
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 25010;
bool f[N];
int a[N];
void init(int n){
for(int i=1;i<=n;++i) f[i] = false;
f[0] = 1;
}
int main(){
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t,n,mx = 0;
cin >> t;
while(t--){
cin >> n;
for(int i=1;i<=n;++i){
cin >> a[i];
mx = max(mx,a[i]);
}
sort(a+1,a+1+n);
init(mx);
int ans = 0;
for(int i=1;i<=n;++i){
//如果这个数可以被表示,说明这个数多余
if(f[a[i]]){
++ans;
continue;
}
for(int j=a[i];j<=mx;++j){
f[j] |= f[j-a[i]];
}
}
cout << (n-ans) << '\n';
}
}