532. 货币系统

题目链接

532. 货币系统

在网友的国度中共有 n 种不同面额的货币,第 i 种货币的面额为 a[i],你可以假设每一种货币都有无穷多张。

为了方便,我们把货币种数为 n、面额数组为 a[1..n] 的货币系统记作 (n,a)

在一个完善的货币系统中,每一个非负整数的金额 x 都应该可以被表示出,即对每一个非负整数 x,都存在 n 个非负整数 t[i] 满足 a[i]×t[i] 的和为 x

然而,在网友的国度中,货币系统可能是不完善的,即可能存在金额 x 不能被该货币系统表示出。

例如在货币系统 n=3, a=[2,5,9] 中,金额 1,3 就无法被表示出来。

两个货币系统 (n,a) 和 (m,b) 是等价的,当且仅当对于任意非负整数 x,它要么均可以被两个货币系统表出,要么不能被其中任何一个表出。

现在网友们打算简化一下货币系统。

他们希望找到一个货币系统 (m,b),满足 (m,b) 与原来的货币系统 (n,a) 等价,且 m 尽可能的小。

他们希望你来协助完成这个艰巨的任务:找到最小的 m

输入格式

输入文件的第一行包含一个整数 T,表示数据的组数。

接下来按照如下格式分别给出 T 组数据。

每组数据的第一行包含一个正整数 n

接下来一行包含 n 个由空格隔开的正整数 a[i]。

输出格式

输出文件共有 T 行,对于每组数据,输出一行一个正整数,表示所有与 (n,a) 等价的货币系统 (m,b) 中,最小的 m

数据范围

1n100,
1a[i]25000,
1T20

输入样例:

2 4 3 19 10 6 5 11 29 13 19 17

输出样例:

2 5

解题思路

数学

即求解最大线性无关组,对于最后选的面额b1,b2,,bm,且其中没有多余的数,即任何一个 bi,不能由其他数系数非负表示出来,而且其一定可以表示 a1,a2,,an 中的任何一个数,反之亦然,假设 bia1,a2,,an,则由题意 bi=t1×ai1+t2×ai2++tk×aik,其中 ti 为正整数,而每个 ai 又可以由 bi 非负表示,即 bi 可由其他 bj 表示,则 bi 是多余的,矛盾,故 b 序列是从 a 序列中选出来的,另外由于大数往往是从小数中组合出来的,所以先排序再筛那些可表示的数

设最大面额为 m,则:

  • 时间复杂度:O(t×n×m)

代码

// Problem: 货币系统 // Contest: AcWing // URL: https://www.acwing.com/problem/content/description/534/ // Memory Limit: 128 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=25005; int n,a[105],t; bool f[N]; int main() { for(cin>>t;t;t--) { cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; sort(a+1,a+1+n); int mx=a[n],res=0; memset(f,0,sizeof f); f[0]=true; for(int i=1;i<=n;i++) { if(f[a[i]])continue; res++; for(int j=a[i];j<=mx;j++)f[j]|=f[j-a[i]]; } cout<<res<<'\n'; } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/15957473.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示