题目地址:
https://www.acwing.com/problem/content/description/826/
艾伦是一个非常富有的人,他在银行存有 n n n元钱,现在由于某些私人原因,他要将钱全部取出用于急用。已知银行的钞票共分 1 , 5 , 10 , 20 , 100 1,5,10,20,100 1,5,10,20,100这 5 5 5种面值。出于携带方便的考虑,艾伦希望组成这 n n n元钱的钞票张数尽可能少。请问在给定 n n n的情况下,组成 n n n元钱的钞票张数最少是多少。
输入格式:
共一行,只包含一个整数
n
n
n。
输出格式:
共一行,只包含一个整数,表示最少的钞票张数。
数据范围:
1
≤
n
≤
1
0
9
1≤n≤10^9
1≤n≤109
思路是贪心,从小到大遍历这些面值,对于每个面值,只有在“不得不用”的时候,才用该面值。例如,对于 1 1 1,显然如果不用 1 1 1,其余面值只能表示出 5 5 5的倍数,所以 n m o d 5 n\mod 5 nmod5就是 1 1 1的个数。对于其余面值的个数以此类推。证明不难,只需注意,对于任意方案,考虑 1 1 1这个面值,如果该面值的个数 x x x大于了 n m o d 5 n\mod 5 nmod5,那么一定有 x ≥ 5 x\ge 5 x≥5(因为如果 x < 5 x<5 x<5,那么 x = n m o d 5 x= n\mod 5 x=nmod5,就矛盾了),这样可以将 5 5 5个 1 1 1替换为 1 1 1个 5 5 5,总钞票数量变少了,矛盾。其余以此类推。代码如下:
#include <iostream>
using namespace std;
int n;
int a[] = {1, 5, 10, 20, 100};
int main() {
scanf("%d", &n);
int res = 0;
for (int i = 0; i <= 3; i++) {
res += n % a[i + 1] / a[i];
n -= n % a[i + 1];
}
res += n / 100;
printf("%d\n", res);
return 0;
}
时空复杂度 O ( 1 ) O(1) O(1)。