最大的奇约数(找规律化简)

题目描述

小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数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)
示例1

输入

7

输出

21

 1 import java.util.LinkedList;
 2 import java.util.List;
 3 import java.util.Scanner;
 4 
 5 /**
 6  * 
 7  * 奇数约数 ------>>>>>>>>>奇数的最大奇约数就是他自己,偶数的最大奇约数就是一直除以二得到的奇数
 8  * 直接计算耗时较长,会超时,我们可以对数列进行分析
 9  * 总体思路: 长度为 n 的数列
10     因为奇数的最大奇数约数就是自己啊,而把所有的奇数提取出来 为一个等差数列,直接求和
11     剩下 偶数数列 我们只需要对数列除二 得到一个 长度为 n/2的数列
12     如:
13         1 2 3 4 5 6 7 8 9 10
14         先取出 奇数列 求和: 1 3 5 7 9 
15         剩下偶数列: 2 4 6 8 10
16         我们接着对偶数列 除以二得到: 1 2 3 4 5
17         接下来我们可以接续对数列取奇数列 :1 3 5
18         剩下偶数列: 2 4 
19         .... 
20         由于每次除二得到的都是 差为1的等差数列,其中必有奇数列和偶数列,我们没必要去构造一个真正的数列,只需要用 n标注下长度即可
21  *
22  */
23 public class Main {
24 
25     static public long f(long n) {
26         long sum = 0;
27         while(n>0) {
28             if (n%2!=0) {
29                 // n为奇数   等差数列求和 s = k(an+a1)/2
30                 sum+=(n/2+1)*(n+1)/2;
31                 
32             }else {
33                 // n为偶数
34                 sum+=(n/2)*(n-1+1)/2;
35             }
36             n = n/2;
37         }
38         return sum;
39     }
40     public static void main(String[] args) {
41         Scanner sc = new Scanner(System.in);
42         long n = sc.nextInt();
43         long s = f(n);
44         System.out.println(s);
45     }
46 }
原文地址:https://www.cnblogs.com/the-wang/p/8981178.html