每日编程系列———最大奇约数

一、题目

小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11.

现在给出一个N,需要求出 f(1) + f(2) + f(3).......f(N)
例如: N = 7 
f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 3 + 7 = 21
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。 
输入描述:
输入一个整数N (1 ≤ N ≤ 1000000000)
输出描述:
输出一个整数,即为f(1) + f(2) + f(3).......f(N)
输入例子:
7
输出例子:
21
二、答案解析
刚读完题,小编马上就有了思路,还有点小得意,写完之后,然后进行了代码测试,谁曾想,算法因为时间复杂度太大,不能通过测试,当然是不合格喽。
以下是不合格的算法,思路很单纯,就是从1到n循环,每次循环求出当前数的最大奇约数,然后累加,这个算法在小编的电脑上(2016的13英寸MAC中配)输入了1,000,000,000,然后用了39657ms计算完毕,晕的一逼,算法写成这样也是没谁了


—————————————华丽的分割线———————————



正确的姿势是这样的:

首先,先讨论一下数的奇约数,奇数的最大奇约数就是本身,偶数要不断地除以2,直到除以2的结果是奇数,那么这个结果就是其最大奇约数
在看我们的题目要求,是求出从1到n之间(包括1和n)的每个数的最大奇约数,然后对它们求和。
1.当n是奇数时,那么在1到n之间共有(n+1)/2个奇数,根据等差数列求和的理论,sn=(首项+末项)*项数/2,这些奇数的和为(n+1)/2*(n+1)/2;
2.当n是偶数时,
那么在1到n之间共有n/2个奇数,这些奇数的和为n/2*n/2,当然在Java中也可以表示为:(n+1)/2*(n+1)/2;
然后这些只是范围内所有奇数的最大奇约数之和,那么剩余的偶数的奇约数之和怎么求呢,是这样的:
我们可以让n除以2,然后求出1到n/2范围内的所有奇数的最大奇约数之和,与之前的求和进行累加,如此让n不断地除以2,直到等于0,那么这所有的累加就是要求的数。

算法的实现如下:








posted @ 2017-02-25 19:26  旧城孤音  阅读(752)  评论(0编辑  收藏  举报