Сумма наибольших нечетных делителей первых 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;;;
СПАСИБО!!