P5020 [NOIP2018 提高组] 货币系统
题目大意:有T组数据,每组数据给你一个货币系统,其中含有n种面值的货币,分别为 a[1…n] 。
现在要输出一种与给定系统等价的所含货币面值种数最小的系统。(两个系统等价就是其能表示出的钱数完全相同,即对于某个面值x,如果能被一个系统所表示,就一定能为另一个系统所表示,反之亦然),输出T行,每行一个系统的最小面值种数m。
算法思路:完全背包变形,贪心。
想法:
1、最终的系统中的所有面值一定是原有系统中的面值,如果引进新面值可能会导致有些原本不能表示出的钱数反而被表示出,我们所要做的就是去除多余的无效面值。
(其实在实际生活中并不是一个好的选择)
来自于洛谷大神“0x3喵酱”的证明
2、首先可以进行从小到大的排序,然后这里有一个贪心思想,即就是优先选择<不能被比他更小的面值所表示出的>当前最小面值,然后将完全背包扫一遍,标记所有当前的面值种类所能表示出的钱数。
3、f数组代表着所有当前的面值种类所能表示出的钱数,所以之前的结果需要保留。
4、一定要在循环中选择最小合法面值时就把总数ans++,不然会出现一堆奇奇怪怪的错误。
#include<bits/stdc++.h>
using namespace std;
int T,n,ans,a[110