人民币的构造
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
我们都知道人民币的面值是 1、2、5、10 ,为什么是这个数值呢,我们分析了下发现,从 1−10 的每个数字都可以由每种面值选出至多一张通过加法和减法(找钱)来构成,(比如: 1+2=3,5−1=4,5+1=6,5+2=7,1+2+5=8,10−1=9 )
但是实际上,我们只需要 1、2、7 三种面值就可以组成 1−10 的每一个数字了
( 1+2=3,7−1−2=4,7−2=5,7−1=6,7+1=8,7+2=9,7+1+2=10 )
那么现在问题来了,给一个数 n ,请问最少需要多少种不同的面值就可以构成从 1−n 的所有数字,注意在构成每一个数字时同种面值不能超过 1 张。
Input
一个数字 n (1<= n <=100000)
Output
一个数字,代表最少需要多少种不同的面值可以构成从 1−n 的所有数字。
Sample input and output
Sample Input | Sample Output |
---|---|
10 | 3 |
Source
第七届ACM趣味程序设计竞赛第三场(正式赛)
解体思路:用公式x>log10(2*n+1)/log10(3)然而WA了的同学注意了,这里在比较整数与小数的大小时注意精度问题,不然会WA到底。
代码如下:
#include<stdio.h>
#include<cmath>
int main(){
int n;
double s,y;
y=log10(3.0);
while(scanf("%d",&n)!=EOF){
s=log10(2*n+1.0)/y;
int x;
x=s;
if(s-x>1e-8)x++;
printf("%d\n",x);
}
return 0;
}
第二种方法:在网上找了人家用数论做的分析,感觉思路非常巧妙;假设当前可以取道[1,K],再增加一个数A,那么此时可以取道的范围是[1,K]U[ A-K,A+K],A是不固定的,为了要尽量时右端点扩大,所取的范围最大,那么此时A-K=K+1,右端点=3*K+1;
代码如下:
#include<stdio.h>
int a[15];
int main(){
int n,i;
a[1]=1;
for(i=2;i<=12;i++){
a[i]=3*a[i-1]+1;
}
while(scanf("%d",&n)!=EOF){
for(i=1;i<=12;i++){
if(n<=a[i]){
printf("%d\n",i);
break;
}
}
}
return 0;
}