100元换成10元5元1元纸币,每种至少一张,一共多少换法

2025-03-21 10:58:43
推荐回答(4个)
回答1:

81种换法
一 ,每种至少一张,实际应为至少10元、5元各一张,1元的5张。共20元,剩下的80元可任意分配。
二,80元的零钱可以如下:
8张10元。1种
7张10元,5元的2、1、0张(差额为1元,下同)。3种
6张10元,5元的4、3、2、1、0张。5种
5张10元,5元的6、5、4、3、2、1、0张。7种
......
1张10元,5元的14、13.....6、5、4、3、2、1、0张。15种
0张10元,5元的16、15、14、13.....6、5、4、3、2、1、0张。17种
三,总的换法为
1+3+5+.....+15+17=81种
看到这个题目的第一感觉就是一个三元一次方程的求解,编程的话,就是三个for循环外加个if判断,瞬间KO。对这个题目来说效率也是可以接受的。可是这根本没有体现出算法的优势。下面我们来仔细推敲下这里面隐藏的规律。



根据上图的规律,即可得到如下代码:

/**
* 1、求解特定实例:要将100元兑换为1元、5元、10元的零钱,请问有多少种兑换方法?
*
* @return
* @author chenchanghan
*/
public static int getDivideWays() {
int count = 0;
for (int i = 0, size = 100 / 10; i // 针对10的每个场景,计算5的组合情况(即,从0个5 到 n( n=(100 - i * 10)/5
// )个5共n+1种情况
count += (100 - i * 10) / 5 + 1;
}
return count;
}

到这里,这个就算解完了,但是这里确实因为分解的元素中包含1,将问题变的简单化了,如果不是1、5、10而是随意的三个数字,改怎么解决呢?同样还是要找出规律来。

下面我们就来分析下10、5、3如何组合成100吧。

首先,0个10的情况下,5和3怎么组合成100呢?正好20*5=100,显然这是不存在10的情况下出现最多5的情况,那还有没有其他的组合情况呢?这时我们就要用到一个最小公倍数(3和5的最小公倍数是15),很显然,我们就可以将”3个5替换成5个3“了。因为最多20个5,所以我们可以继续用”3个5替换成5个3“,直到最后剩下2个5。综上0个10的情况下,5可以出现的次数分别为20、17、14、11、8、5、2,所以该场景下共有7中组合方式。

其次,1个10的情况下,5和3怎么组合成100呢?我们还是从5来出发,5*18=90,1个10的情况下,组合成100,最多可以出现18次,同理还是用”3个5替换成5个3“。最终1个10的情况下,5可以出现的次数分别为18、15、12、9、6、3、0。该场景下也有7种组合方式。

同理,依次分析下去。

根据上面的规律,得出代码如下:


/**
* 2、组合元素一般化:将total元兑换为large元、middle元、small元的零钱,请问有多少种兑换方法?
*
* @param total
* @param large
* @param middle
* @param small
* @return
* @author chenchanghan
*/
public static int getDivideWays(int total, int large, int middle, int small) {
if (total > 0 && small > 0 && middle > small && large > middle) {
int count = 0;
int LCM = getLeastCommonMutiple(middle, small);
int substituteUnit = LCM / middle;
for (int i = 0, size = total / large; i int restTotal = total - i * large;
if (restTotal > 0) {
// actualMaxMiddleNum>=0,表示restTotal正好可以有x个middle和y个small拼凑起来(x、y是大于等于0的整数)
int actualMaxMiddleNum = getActualMaxMiddleNum(restTotal, middle, small);
if (actualMaxMiddleNum >= substituteUnit) {
// actualMaxMiddleNum >=substituteUnit,表示可以将substituteUnit个middle替换成LCM/small个small
// 可以换多少次呢?显然可以换0、1...actualMaxMiddleNum/substituteUnit,即:actualMaxMiddleNum/substituteUnit+1
count += actualMaxMiddleNum / substituteUnit + 1;
} else if (actualMaxMiddleNum >= 0) {
// 0// 因为count++;
}
} else {
// 正好被large完美匹配了
count++;
}
}
return count;
} else {
throw new IllegalArgumentException();
}
}

/**
* 获得方程:x*middle + y*small = restTotal 中x最大的取值。
*
* @param restTotal
* @param middle
* @param small
* @return
* @author chenchanghan
*/
private static int getActualMaxMiddleNum(int restTotal, int middle, int small) {
int modMiddle = restTotal % middle;
int maxMiddleNum = restTotal / middle;
int actualMaxMiddleNum = -1;
if (modMiddle == 0 || modMiddle == small) {
actualMaxMiddleNum = maxMiddleNum;
} else {
// 无法使用最大数量(即:maxMiddleNum)的middle和small组合成restTotal,
// 则需要逐步减少middle的个数,进而增加small的个数,来尝试组合成restTotal。
int minusMiddleNum = getMinusMiddleNum(middle, small, modMiddle, maxMiddleNum);
if (minusMiddleNum > 0) {
// 表示可以形成一个拥有最大middle数的组合,即: (maxMiddleNum - minusMiddleNum)*middle + y*small = restTotal ;
actualMaxMiddleNum = maxMiddleNum - minusMiddleNum;
} else {
// middle和small无论怎么组合都无法拼凑成restTotal,即:x*middle + y*small = restTotal 的整数解不存在
actualMaxMiddleNum = -1;
}
}
return actualMaxMiddleNum;
}

/**
*
* @param middle
* @param small
* @param modMiddle
* @param maxMiddleNum
* @return
* @author chenchanghan
*/
private static int getMinusMiddleNum(int middle, int small, int modMiddle, int maxMiddleNum) {
int minusMiddleNum = -1;
for (int i = 1; i if ((middle * i + modMiddle) % small == 0) {
minusMiddleNum = i;
break;
}
}
return minusMiddleNum;
}

/**
* 求两个数的最小公倍数。
*
* @param middle
* @param small
* @return
* @author chenchanghan
*/
private static int getLeastCommonMutiple(int m, int n) {
return m * n / getGreatestDivisor(m, n);
}

/**
* 求两个数的最大公约数。
*
* @param m
* @param n
* @return
* @author chenchanghan
*/
private static int getGreatestDivisor(int m, int n) {
int tmp = 0;
if (m tmp = m;
m = n;
n = tmp;
}
while ((tmp = m % n) != 0) {
m = n;
n = tmp;
}
return n;
}



我们再来推广下,将分解的元素变成3个以上,具体见如下代码:

/**
* 3、元素个数一般化:将total元兑换为a元、b元、c元、....的零钱,请问有多少种兑换方法?
*
* @param total
* @param elements
* @return
* @author chenchanghan
*/
public static int getDivideWays(int total,int[] elements){
if(elements!=null && elements.length>=3){
int count = 0 ;
if(elements.length == 3){
count += getDivideWays(total,elements[0],elements[1],elements[2]);
}else{
int large = elements[0];
int[] subElements = new int[elements.length-1];
System.arraycopy(elements, 1, subElements, 0, subElements.length);
for (int i = 0, size = total / large; i int restTotal = total - i * large;
if (restTotal != 0) {
count += getDivideWays(restTotal, subElements);
} else {
count++;
}
}
}
return count ;
}else{
throw new IllegalArgumentException();
}
}

回答2:

81种换法
一 ,每种至少一张,实际应为至少10元、5元各一张,1元的5张。共20元,剩下的80元可任意分配。
二,80元的零钱可以如下:
8张10元。1种
7张10元,5元的2、1、0张(差额为1元,下同)。3种
6张10元,5元的4、3、2、1、0张。5种
5张10元,5元的6、5、4、3、2、1、0张。7种
......
1张10元,5元的14、13.....6、5、4、3、2、1、0张。15种
0张10元,5元的16、15、14、13.....6、5、4、3、2、1、0张。17种
三,总的换法为1+3+5+.....+15+17=81种。

拓展资料
各国货币单位
1、中国货币(元)
中华人民共和国的法定货币是人民币,中国人民银行是国家管理人民币的主管机关,负责人民币的设计、印制和发行。人民币的单位为元,人民币的辅币单位为角、分。1元等于10角,1角等于10分。人民币符号为元的拼音首字母大写Y加上两横即“¥”

2、英国货币(英镑)
英镑是英国国家货币和货币单位名称。英镑主要由英格兰银行发行,但亦有其他发行机构。最常用于表示英镑的符号是£。国际标准化组织为英镑取的ISO 4217货币代码为GBP(Great Britain Pound)。除了英国,英国海外领地的货币也以镑作为单位,与英镑的汇率固定为1:1。

3、美国货币(美元)
美元(United States dollar 货币缩写:USD;ISO 4217货币代码:USD;符号:USA$)是美利坚合众国的法定货币。目前流通的美元纸币是自1929年以来发行的各版钞票。

4、泰国货币(泰铢)
泰铢(ISO 4217码:THB)是泰国官方货币,由泰中央银行泰国银行发行,1铢等于100萨当(satang)。自第9序列至第16序列泰铢每种纸币、铸币的正面均印有、铸有泰王拉玛九世普密蓬.阿杜德头像。自2018年4月6日起,发行第17序列泰铢,纸币、硬币均改为泰王拉玛十世玛哈.哇集拉隆功头像。

5、俄罗斯货币(卢布)
卢布,符号: _(原符号Rbs. Rbl)。货币代码:RUB。使用地区:俄罗斯以及自行宣布独立的阿布哈兹及南奥塞梯。通胀率:7%,俄罗斯卢布(Рублевка)是俄罗斯的本位货币单位。辅币是戈比(Копейка)。1卢布=100戈比。

回答3:

81种换法
一 ,每种至少一张,实际应为至少10元、5元各一张,1元的5张。共20元,剩下的80元可任意分配。
二,80元的零钱可以如下:
8张10元。1种
7张10元,5元的2、1、0张(差额为1元,下同)。3种
6张10元,5元的4、3、2、1、0张。5种
5张10元,5元的6、5、4、3、2、1、0张。7种
......
1张10元,5元的14、13.....6、5、4、3、2、1、0张。15种
0张10元,5元的16、15、14、13.....6、5、4、3、2、1、0张。17种
三,总的换法为
1+3+5+.....+15+17=81种

回答4:

很多啊!