练习-印假钞

Description

Bob最近想试一下印假钞,因为印刷超过m面值的假钞可能被抓,因此Bob会印刷总面值m元的假钞。对印刷的假钞有以下要求

  • 每张假钞的面值都在 1m元范围内并且都是整数
  • 可以有任意张1元的假钞,其他面值的假钞任意两张的面值都不同

  • 对于 1m元的所有整数价值,都可以用假钞中的一部分凑出来

在以上条件下,请问最少印多少假钞能满足要求

Input

包含一个整数m(0m109)m(0≤m≤109)

Output

两行,第一行一个整数h,表示所印假钞个数

第二行表示每张假钞的面值,由小到大输出,空格隔开

Sample Input

3

Sample Output

2

1 2


解题思路:

二分的思想。以数字8为例,8可以分为4+4,然后4可分为2+2,2可以分为1+1,结束划分,故8可表示为8=4+2+1+1;

同理,以11为例,11可以划分为6+5,5可以划分为3+2,2可以划分为1+1,故11可表示为11=6+3+1+1;画个二叉树也许更好理解......

总结:对于奇数的划分,每次二分向上取整,然后对奇数中还未划分的整数继续以类似的形式划分即可......;对于偶数,直接二分就行了。

#include<iostream>
#include<math.h>
#include<stdio.h>
using namespace std;
int a[10000000];
int main(int argc, char** argv) {
	int m;
	while(scanf("%d",&m)!=EOF)
	{
		if(m==0)//特殊情况....
		{
			printf("0\n"); 
			continue;
		}
		int cnt=0;
		while(m!=1)//结束部分不能再继续二分了,所以是1
		{
			int x=ceil(m/2.0);//二分且向上取整
			a[cnt]=x;
			cnt++;
			int y=m-x;
			m=y;
		}
		a[cnt]=m;
		printf("%d\n",cnt+1);
		for(int i=cnt;i>=0;i--)
		{
			printf("%d ",a[i]);
		}
		printf("\n");
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/zhuixun_/article/details/80809378