题目描述
小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数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,需要求出 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 }