Сумма наибольших нечетных делителей первых n чисел

Я недавно работал над topcoder, и я наткнулся на этот вопрос, который я не могу понять. Вопрос в том, чтобы найти F(n) = f(1)+f (2)+....+f(n) для заданного "n" такого, что f (n) является наибольшим нечетным делителем для n. Есть много тривиальных решений для ответа; однако я нашел это решение очень интригующим.

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

однако я не совсем понимаю, как получить рекурсивное отношение из постановки задачи, такой как это. Может кто поможет наружу?

5 ответов


Я считаю, что они пытаются использовать следующие факты:

  • f (2k+1) = 2k+1, т. е. наибольшим нечетным делителем нечетного числа является само число.
  • f(2k) = f (k). я.е наибольший нечетный делитель числа четным числом 2М такой же, как наибольший нечетный делитель числа m.
  • сумма первых k нечетных чисел равна K^2.

теперь разбиения {1,2,..., 2m+1} as {1,3,5,7,...} и {2,4,6,..., 2m} и попробуйте применить приведенные выше факты.


вы можете использовать динамический подход также используя вспомогательные помещения

int sum=0;
int a[n+1];
for(int i=1;i<=n;i++){
  if(i%2!=0)
  a[i] = i;
  else
  a[i] = a[i/2];
}
for(int i=1;i<=n;i++){
  sum+=a[i];
}
cout<<sum;

поскольку, когда число нечетное, то само число будет наибольшим нечетным делителем, а[i] будет хранить его значение, а когда число четное, то a[Число/2] будет храниться в[i], потому что для четного числа наибольший нечетный делитель числа/2 будет наибольшим нечетным делителем числа.

его также можно решить, используя три случая, когда число нечетно, а затем добавить само число, если число мощность 2 затем добавить 1 еще, если число четное, кроме мощности 2 разделить его на 2, пока не получите нечетное и добавить, что нечетное к сумме.


Я не вижу, как этот алгоритм может работать для описанной вами проблемы. (Я собираюсь предположить, что "N" и "n" относятся к одной и той же переменной).

учитывая n = 12.

наибольший нечетный делитель 3 (остальные 1, 2, 4, 6 & 12)

F (12) для этого f(1) + f(2) + f(3) или 1 + 1 + 3 или 5.

используя этот алгоритм:

к = (12+1)/2 или 6

и мы возвращаем 6 * 6 + f(6), или 36 + некоторое число, которое не будет минус 31.


если бы это была Java, я бы сказал:

 import java.util.*;
 int sum_largest_odd_factors (int n){
      ArrayList<Integer> array = new ArrayList();//poorly named, I know
      array.add(1);
      for(int j = 2; j <= n; j++){
           array.add(greatestOddFactor(j));
      }
      int sum = 0;
      for(int i = 0; i < array.size(); i++){
           sum += array.get(i); 
      }
      return sum;
 }
 int greatestOddFactor(int n){
      int greatestOdd = 1;
      for(int i = n-((n%2)+1); i >= 1; i-=2){
          //i: starts at n if odd or n-1 if even 
          if(n%i == 0){
               greatestOdd = i;
               break;
               //stop when reach first odd factor b/c it's the largest
          }
      }
      return greatestOdd;
 }

это, по общему признанию, утомительно и, вероятно, операция O(n^2), но будет работать каждый раз. Я оставлю вам перевод на C++ , поскольку Java и J-единственные языки, с которыми я могу работать (и даже на низком уровне). Мне любопытно, какие гениальные алгоритмы могут придумать другие люди, чтобы сделать это намного быстрее.


Если u ищет сумму всех нечетных делителей до n..

сумма всех нечетных делителей первых n чисел

...

for(long long int i=1;i<=r;i=i+2)
{
    sum1=sum1+i*(r/i);   
}

для суммы всех делителей в диапазоне от l до r

for(long long int i=1;i<=r;i=i+2)
{
    sum1=sum1+i*(r/i); 
}

for(long long int i=1;i<l;i=i+2)
{
    sum2=sum2+i*((l-1)/i); 
}

ans=sum1-sum2;;;

СПАСИБО!!