重点内容
鬼谷子非常聪明,正因为这样,他非常繁忙,经常有各诸侯车的特派员前来向他咨询时政。
有一天,他在咸阳游历的时候,朋友告诉他在咸阳最大的拍卖行(聚宝商行)将要举行一场拍卖会,其中有一件宝物引起了他极大的兴趣,那就是无字天书。
但是,他的行程安排得很满,他已经买好了去邯郸的长途马车票,不巧的是出发时间是在拍卖会快要结束的时候。于是,他决定事先做好准备,将自己的金币数好并用一个个的小钱袋装好,以便在他现有金币的支付能力下,任何数目的金币他都能用这些封闭好的小钱的组合来付账。
鬼谷子也是一个非常节俭的人,他想方设法使自己在满足上述要求的前提下,所用的钱袋数最少,并且不有两个钱袋装有相同的大于1的金币数。假设他有m个金币,你能猜到他会用多少个钱袋,并且每个钱袋装多少个金币吗?
输入输出格式
输入格式:
包含一个整数,表示鬼谷子现有的总的金币数目m。其中,1≤m ≤1000000000。
输出格式:
两行,第一行一个整数h,表示所用钱袋个数
第二行表示每个钱袋所装的金币个数,由小到大输出,空格隔开
输入输出样例
输入样例
3
输出样例
2
1 2
分析
疯狂打表推规律
真的牛逼了
首先我觉得这个有点不对劲,然后看了一眼数据。。发现O(N)显然不可能,所以考虑O(LogN),然后LogN(非常自然地)想到了二进制
然后打了一波表,发现:
首先我们知道二进制转回十进制是要调转过来的嘛:
最后一位乘1,倒数第二位乘2,倒数第三位乘4等等
然后我发现,它所需要的袋子数量是和二进制位数一样的,第i个袋子我以为也遵循第i为二进制数的规律,结果不对,最后一直推到32才发现,原来第i位袋子的数量等于:
(n-2^(m(袋子总数)-i))/2^(m-i+1)+1
然后就是喜闻乐见的1AC时间啦
#include <iostream>
#include <cstdio>
using namespace std;
long long x,i,n;
long long a[32];
int main()
{
scanf("%lld",&n);
x=1;
while (x<n)
{
x*=2;
i++;
a[i]=(n-x/2)/x+1;
}
printf("%lld\n",i);
while (i>0)
{
printf("%lld ",a[i]);
i--;
}
}