Odd Divisors#1520

Odd Divisors (Editorial)

If is odd, then f(n) = n.

If is even, then f(n) = f(n / 2).

Let

g(n) = f(1) + f(2) + ... + f(n)

Consider the partition of the set of positive integers from to into two subsets:

Among the positive integers from to , there are exactly

Then:

f(1) + f(3) + f(5) + ... + f(2k - 1) = \\ 1 + 3 + 5 + … + (2k - 1) = \\ {1 +2k - 1\over 2} \cdot k = k^2

At the same time:

f(2) + f(4) + f(6) + ... + f(2l) = \\ f(1) + f(2) + f(3) + ... + f(l) = \\ g(l) = g(\left\lfloor n / 2 \right\rfloor)

To terminate the recursion, let g(0) = 0. Thus:

g(n) = \begin{cases} k^2 + g(\left\lfloor n / 2 \right\rfloor), k = (\left\lfloor n + 1) / 2 \right\rfloor \\ 0, n = 0 \end{cases}

Example

Consider the first test case where n = 7.

Among the positive integers from to there are exactly:

g(7) = \left\lfloor 7 + 1 \over 2 \right\rfloor^2 + g\left(\left\lfloor 7 \over 2 \right\rfloor\right) = 16 + g(3) = \\ 16 + \left\lfloor 3 + 1 \over 2 \right\rfloor^2 + g\left(\left\lfloor 3 \over 2 \right\rfloor\right) = 16 + 4 + g(1) = 16 + 4 + 1 = 21

Algorithm implementation

Implement the function g.

long long g(long long n)
{
  long long k = (n + 1) / 2;
  if (n == 0) return 0;
  return k * k + g(n / 2);
}

The main part of the program. For each test case read the input value of and print .

while(scanf("%lld",&n) == 1)
  printf("%lld\n",g(n));

Java implementation

import java.util.*;

public class Main
{
  static long g(long n)
  {
    long k = (n + 1) / 2;
    if (n == 0) return 0;
    return k * k + g(n / 2);
  }
	
  public static void main(String[] args)
  {
    Scanner con = new Scanner(System.in);
    while(con.hasNext())
    {
      long n = con.nextLong();
      System.out.println(g(n));
    }
  }
}

Python implementation

Implement the function g.

def g(n):
  if n == 0:
    return 0
  k = (n + 1) // 2
  return k * k + g(n // 2)

The main part of the program. For each test case read the input value of and print .

for line in sys.stdin:
  n = int(line)
  print(g(n))