2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Нахождение всех делителей числа
Сообщение02.07.2014, 22:10 


10/05/13
251
Недавно встала такая задача:
Дано некое положительное число, надо найти все его делители, кроме его самого.
Задача в том чтобы написать как можно более быстрый алгоритм, и конечно же
корректный.
Первая идея была, перебирать меньшие числа, проверяя на делимость, но полный
перебор не дал широких пределов применения, уже для решения задачи например для
$2^{32}$, этот алгоритм работал очень долго, после нескольких модификаций
я получил вот такой вот алгоритм, верхняя оценка сложности в худшем случае $O(\sqrt{n})$.
Алгоритм заполняет вектор детелями числа.
Код:
void find_divs( int n, vector<int> & divs ) {
   int d, dlim, m = 1;
   divs.push_back(1);

   dlim = sqrt( n );
   for ( d = 2; d <= dlim; ++d ) {
      if ( n%d == 0 ) {
         divs.push_back(m*d);
         if ( m*d != n/d )
            divs.push_back(n/d);
         n /= d;
         m *= d;
         dlim = sqrt( n );
      }
   }
}


Можно ли как-то улучшить алгоритм? Или есть более быстрые методы решения этой задачи?

 Профиль  
                  
 
 Re: Нахождение всех делителей числа
Сообщение02.07.2014, 22:18 
Заслуженный участник


04/05/09
4587
frankenstein в сообщении #883340 писал(а):
Можно ли как-то улучшить алгоритм?
Для начала надо бы его исправить. Проверьте, что у вас получится для 12 и 36.
frankenstein в сообщении #883340 писал(а):
Или есть более быстрые методы решения этой задачи?
Сначала получите разложение входного числа на простые множители. Дальше перебираете все комбинации простых множителей.

 Профиль  
                  
 
 Re: Нахождение всех делителей числа
Сообщение02.07.2014, 22:28 


10/05/13
251
Цитата:
Для начала надо бы его исправить. Проверьте, что у вас получится для 12 и 36.

Да, алгоритм работает неправильно ). Думаю эта правильная:
Код:
void find_divs( int n, vector<int> & divs ) {
   int d, dlim, m = 1;
   divs.push_back(1);

   dlim = sqrt( n );
   for ( d = 2; d <= dlim; ++d ) {
      if ( n%d == 0 ) {
         divs.push_back(m*d);
         if ( m*d != n/d )
            divs.push_back(n/d);
         n /= d;
         m *= d;
         dlim = sqrt( n );
      }
   }
}


Цитата:
Сначала получите разложение входного числа на простые множители. Дальше перебираете все комбинации простых множителей.

Да, была такая идея, на перебор комбинаций уйдет где-то $2^{number of prime factors of n}$ итераций, как в этом случае оценить сложность алгоритма? Есть ли какая нибудь формула для вычисления количества простых множителей числа. Или хотя бы надо оценить верхнюю границу, т.е. найти число, которое разлагается на максимальное число простых множителей.

 Профиль  
                  
 
 Re: Нахождение всех делителей числа
Сообщение02.07.2014, 22:37 
Заслуженный участник


04/05/09
4587
frankenstein в сообщении #883346 писал(а):
Думаю эта правильная:
Надеюсь вы проверили хотя бы на 12 и 36?

Сложность алгоритма, как минимум - собственно число делителей, а перебор по простым делителям даст именно такую сложность (без учёта факторизации). Естественно, не надо хранить и перебирать каждую двойку отдельно - нужно лишь их количество.

 Профиль  
                  
 
 Re: Нахождение всех делителей числа
Сообщение04.07.2014, 08:41 


23/01/07
3497
Новосибирск
Может, поможет следующее:

Если $n= x^ay^b... $

то все делители можно определить из выражения: $(x^a+x^{a-1}+...+1)(y^b+y^{b-1}+...+1)...$

Соответственно, для собственных делителей необходимо после раскрытия скобок исключить первое слагаемое.

 Профиль  
                  
 
 Re: Нахождение всех делителей числа
Сообщение07.08.2014, 14:08 


10/05/13
251
Хотелось быстрее результата как программу, которая может сделать это за позволительное время и вот она:
Код:
void get_div(int n, vector<int> & divs) {
int d, dlim;
dlim = sqrt( n );
for (d = 2; d <= dlim; ++d) {
  if (n%d == 0) {
   divs.push_back(d);
    if ( d != n/d )
     divs.push_back(n/d);
  }
}
}

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 6 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group