题目描述
将任意给定的整百元钞票,兑换成10元、20元、50元小钞票形式。输出兑换方案总数。
输入
输入需要兑换的钞票总数n。
输出
输出方案总数。
样例输入
100
样例输出
10
数据范围限制
100<=n<=1000000
常规0
#include <stdio.h>
#include <stdlib.h>
int main(){
int i,a,b,c,sum=0;
scanf("%d",&i);
for(a=0;a<=i/50;a++){
for(b=0;b<=i/20;b++){
for(c=0;c<=i/10;c++){
if(a*50+b*20+c*10==i){
sum++;
}
}
}
}
printf("%d",sum);
return 0;
}
穷举法很容易想到,只要让3个整数挨个穷举就可以了。
虽然还可以在循环范围上进行优化,不过那在接下来的改进面前算不了什么。
但是因为数据范围的问题,会超时TLE,不得不让我们动起了歪脑筋(可能在大佬中就是正常思路)。
为了在文中方便讨论,代码中的i文中变成100i
改进1
因为题目的数据十分友善,可以利用一下。
数学点的描述:
看c好欺负:
当c存在时符合条件:
这样,就可以消去一个元。
//...
for(a=0;a<=i/50;a++){
for(b=0;b<=i/20;b++){
if(a*50+b*20<=i){
sum++;
}
}
}
//...
改进2
这当然不是最终形态啦,还可以改进的更加优秀。
既然c可以算出来,那b可不可以呢?
易解得
然后就很容易计算出sum在b的一次循环内增加了多少,但要注意取整的界限问题
//...
for(a=0;a<=i/50;a++){
sum+=(i-50*a)/20+1;
}
//...
改进3—超进化
没错,已经简单成这样了还能简化,如果不能这么皮还写这篇干什么。
官方题解中几乎都是这个级别,但csdn上却搜不到,很奇怪。
那就自己写一篇吧!
刚才本质上已经相当于数列求和,把a=0单独提出
展开,分奇偶讨论,去掉取整
简化成这样,配的上超进化这个名字
最终代码
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
scanf("%d",&i);
i/=100;
printf("%d",5*i*i+4*i+1);
return 0;
}
完结撒花
2018年8月2日02点31分