---恢复内容开始---
我们都知道人民币的面值是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 |
分析:
事实上题面是有点迷惑人的,因为前三个最佳的面额并不是1,2,7,而是1, 3, 9
1, 2, 7只能表示1-10的数,但1, 3, 9可以表示1-13的数。
我们用A[n]表示第n个面额,用sum[n]表示前n个面额之和,不难看出A[1], A[2]……A[n]能表示的范围为1,2……sum[n]
题目要求面额最小,也就相当于A[1]……A[n]能表示的范围尽可能的大,所以
|-----------A[n] A[n]+1-----------------------------------------------------------------A[n+1]--------------------------------------------------|
|--------------------------sum[n]-------------------------------------|
A[n+1] - sum[n] = A[n] + 1
据此,可以写出代码
1 #include <cstdio> 2 3 using namespace std; 4 5 int main() { 6 int n; 7 int cnt = 1; 8 int sum = 1; 9 int nw = 1; 10 scanf("%d", &n); 11 while (sum < n) { 12 nw = sum*2+1; 13 sum += nw; 14 cnt++; 15 } 16 printf("%d\n", cnt); 17 18 return 0; 19 }
事实上这并不是最简洁的方法,
gdb中观察上面代码,不难发现A[n]为1, 3, 9, 27……
猜想A[n]=3n-1
证明嘛……我再想想。
---恢复内容结束---