网站建设哈尔滨网站设计3,windows优化大师会员,电商推广,wordpress绑定手机验证链接#xff1a; 文章目录题目描述题解#xff1a;代码#xff1a;题目描述 在网友的国度中共有n种不同面额的货币#xff0c;第i种货币的面额为a[i]#xff0c;你可以假设每一种货币都有无穷多张。为了方便#xff0c;我们把货币种数为n、面额数组为a[1…n]的货币系统记…链接
文章目录题目描述题解代码题目描述 在网友的国度中共有n种不同面额的货币第i种货币的面额为a[i]你可以假设每一种货币都有无穷多张。为了方便我们把货币种数为n、面额数组为a[1…n]的货币系统记作(n,a)。 在一个完善的货币系统中每一个非负整数的金额x 都应该可以被表示出即对每一个非负整数x都存在n个非负整数t[i] 满足a[i] x t[i] 的和为x。然而在网友的国度中货币系统可能是不完善的即可能存在金额x不能被该货币系统表示出。例如在货币系统n3, 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。 示例1 输入
2
4
3 19 10 6
5
11 29 13 19 17输出
2
5说明 在第一组数据中货币系统(2, [3,10])和给出的货币系统(n, a)等价并可以验证不存在m 2的等价的货币系统因此答案为2。 在第二组数据中可以验证不存在m n的等价的货币系统因此答案为5。 备注: 1 T 20, 1 n 100, 1 a[i] 25000
题解
首先伤感一分钟纪念我逝去的oi 我唯一参加过的一届的noip让我永生难忘 我记得当时考完后有人戏称为大凯的疑惑 我们来看一下题先知道什么是货币系统其实就是这几种不同面值的钱任意组合出其他钱。 如果一个货币系统中有3有6那么6就可以省略因为6可以由两个3组成这样我们就可以得到一个最小货币系统这个货币系统是原来的子集且里面每种面值都是独一无二不可代替的与原本的是等价关系 我们可以从最小面值开始因为最小面值肯定无法代替然后面值依次变大 这样题意就成了给你一堆数每个数可用无数次问能组成多少数 这不就是完全背包问题 我们先排序 然后对前i-1个货币进行完全背包不能被取代的币值也加入背包中到最后看看有多少
f[i]表示当前这个数x之前的数能不能组成i如果f[x]等于1那么说明x可以删了删掉即可如果f[x]是0那么x不能删就按完全背包的方式更新f数组。官方题解引入
代码
#includebits/stdc.h
using namespace std;
typedef long long ll;
const int maxn25002;
int a[320];
bool f[maxn];
int tot0;
int n;
int main()
{int T;cinT;while(T--){tot0;cinn;memset(a,0,sizeof(a));for(int i1;in;i)cina[i];sort(a1,a1n);memset(f,0,sizeof(f));f[0]1;// coutf[0]endl;for(int i1;in;i){if(!f[a[i]]){tot;//如果这个货币独一不二不能被组成则保留// printf(j%d %d\n,a[i],f[a[i]]); }else continue;for(int ja[i];jmaxn;j){if(f[j-a[i]])f[j]1;else if(f[j])continue; //当前j能否被构造 // printf(j-a[i]%d %d\n,j-a[i],f[i-a[i]]); // printf(j%d %d\n,j,f[j]); }}couttotendl;}return 0;
}