货币系统

简单分析一下,不难得出结论:
m最小时,相当于把A系统简化,除去可以被A中其他元素组合的多余元素。
接下来是重点!!
若有一个数s能被之前的数a_i表示出来,那么(s - a_i)也能被之前的数表示出来
所以我们用\(f[i]\)表示\(i\)能否被表示出来。
我们定义边界\(f[0] = 1\)
每次把处理到的\(a[i]\)标记,然后筛除比a[i]大的那些可表示为\(a[i] + a[k]\ (0 < k < i)\)的数

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int T, n, a[25005], dp[25005], ans = 0;
int read(){
    int x = 0, ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x;
}
int main(){
    cin >> T;
    while(T--){
        memset(a, 0, sizeof a);
        memset(dp, 0, sizeof dp);
        n = read(), ans = n;
        for(int i = 1; i <= n; i++)
            a[i] = read();
        sort(a + 1, a + n + 1);
        dp[0] = 1;
        for(int i = 1; i <= n; i++){
            if(dp[a[i]]){
                ans--;
                continue;
            }
            for(int j = a[i]; j <= a[n]; j++)
                dp[j] |= dp[j - a[i]];
        }
        cout << ans <<"\n";
    }
    return 0;
}
01-08 07:16