题目:小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数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的数组
代码:
import java.util.Scanner; public class MostOddNumber { public static void main(String[] args){ Scanner scan = new Scanner(System.in); int n = scan.nextInt(); if(n == 0){ System.out.println("-1"); } int[] arr = new int[n+1]; arr[0] = 0; int sum = 0; for(int i = 0; i < n+1; i++){ if((i&1) == 1){ arr[i] = i; }else{ arr[i] = arr[i/2]; } sum = sum + arr[i]; } System.out.println(String.valueOf(sum)); } }
运行结果:
改进代码
找出最大奇约数之和的规律
sum(i) = f(1) + f(2) + f(3) + … + f(i)
分情况讨论:1.如果i为偶数 sum(i) = f(1) + f(2/2) + f(3) + f(4/2) + f(5) + ... + f(i/2) = sum(i/2) + 1 + 3 + 5 + ... + (i-1) = sum(i/2) + i*(i/2)/2 等差数列求和公式:(首项+末项)*项数/2 2.如果为奇数 sum(i) = f(1) + f(2) + f(3) + ... + f(i) = sum(i-1) + i
根据上述思路,则不需要用一个大小为n+1的数组来存放各个元素的最大奇约数
代码:
需要注意的是:从控制台获取的值是long型的,和的类型也是long型的,不然会溢出(虽然题目没有提示)import java.util.*; public class MostOddNumber{ public static void main(String[] args){ Scanner scan = new Scanner(System.in); long n = scan.nextLong(); if(n == 0){ System.out.println("-1"); } long sum = 0; while(n > 0){ if((n&1) == 0){ sum += n*n/4; n = n/2; }else{ sum += n; n--; } } System.out.println(sum); } }
- 运行结果