Вот мой код:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
#define pii pair<int, int>
#define MAX 46656
#define LMT 216
#define LEN 4830
#define RNG 100032
unsigned base[MAX/64], segment[RNG/64], primes[LEN];
#define sq(x) ((x)*(x))
#define mset(x,v) memset(x,v,sizeof(x))
#define chkC(x,n) (x[n>>6]&(1<<((n>>1)&31)))
#define setC(x,n) (x[n>>6]|=(1<<((n>>1)&31)))
// http://zobayer.blogspot.com/2009/09/segmented-sieve.html
void sieve()
{
unsigned i, j, k;
for (i = 3; i<LMT; i += 2)
if (!chkC(base, i))
for (j = i*i, k = i << 1; j<MAX; j += k)
setC(base, j);
primes[0] = 2;
for (i = 3, j = 1; i<MAX; i += 2)
if (!chkC(base, i))
primes[j++] = i;
}
//http://www.geeksforgeeks.org/print-all-prime-factors-of-a-given-number/
vector <pii> factors;
void primeFactors(int num)
{
int expo = 0;
for (int i = 0; primes[i] <= sqrt(num); i++)
{
expo = 0;
int prime = primes[i];
while (num % prime == 0){
expo++;
num = num/prime;
}
if (expo>0)
factors.push_back(make_pair(prime, expo));
}
if (num >= 2)
factors.push_back(make_pair(num, 1));
}
vector <int> divisors;
void setDivisors(int n, int i) {
int j, x, k;
for (j = i; j<factors.size(); j++) {
x = factors[j].first * n;
for (k = 0; k<factors[j].second; k++) {
divisors.push_back(x);
setDivisors(x, j + 1);
x *= factors[j].first;
}
}
}
int main() {
sieve();
int n, x, i;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x;
primeFactors(x);
setDivisors(1, 0);
divisors.push_back(1);
sort(divisors.begin(), divisors.end());
cout << divisors.size() << "\n";
for (int j = 0; j < divisors.size(); j++) {
cout << divisors[j] << " ";
}
cout << "\n";
divisors.clear();
factors.clear();
}
}
Первая часть, сито() используется для нахождения простых чисел и поместить их в простых числах [] массиве. Перейдите по ссылке, чтобы узнать больше об этом коде (побитное сито).
Вторая часть primeFactors (x) принимает в качестве входных данных целое число (x) и обнаруживает его простые множители и соответствующий показатель и помещает их в векторные факторы []. Например, primeFactors (12) заполнит факторы [] следующим образом:
factors[0].first=2, factors[0].second=2
factors[1].first=3, factors[1].second=1
как 12 = 2^2 * 3^1
The setDivisors третья часть() рекурсивно вызывает себя, чтобы вычислить все делители х, используя векторные множители [] и помещая их в векторные делители [].
Он может вычислять дивизоры любого числа, которое вписывается в int. И это довольно быстро.
Что вы думаете, «не очень хорошо» о вашем предлагаемом подходе простое число? Сверху моей головы это звучит как наиболее приемлемый подход для больших чисел. Известно, что факторизация является «трудной» (т. Е. Медленной) проблемой. От этого факта зависит большая часть мира. Знаете ли вы максимальный размер ввода, который вы ожидаете? Менее общий подход может заключаться в том, чтобы предварительно вычислить таблицу простых чисел, подходящую для диапазона ввода, и использовать это. – BoBTFish
Я думаю, что «получить все возможные комбинации этих основных факторов» не может быть эффективным. – zangw
Лучше в среднем получить только простые коэффициенты, а затем сгенерировать комбинации. Это не помогает, если исходное число является простым, но если это не так, вы будете делать гораздо меньше делений. – harold