Selon ce post , nous pouvons obtenir tous les diviseurs d’un nombre grâce aux codes suivants.
for (int i = 1; i <= num; ++i){
if (num % i == 0)
cout << i << endl;
}
Par exemple, les diviseurs du nombre 24
sont 1 2 3 4 6 8 12 24
.
Après avoir cherché quelques articles connexes, je n’ai trouvé aucune bonne solution. Existe-t-il un moyen efficace d'y parvenir?
Ma solution:
Cependant, cela ne semble pas être bon.
Les facteurs sont appariés. 1
et 24
, 2
et 12
, 3
et 8
, 4
et 6
.
Une amélioration de votre algorithme pourrait consister à itérer à la racine carrée de num
au lieu de tout le chemin à num
, puis à calculer les facteurs liés en utilisant num / i
.
Vous devriez vraiment vérifier jusqu'à la racine carrée de num comme sqrt (num) * sqrt (num) = num:
Quelque chose sur ces lignes:
int square_root = (int) sqrt(num) + 1;
for (int i = 1; i < square_root; i++) {
if (num % i == 0&&i*i!=num)
cout << i << num/i << endl;
if (num % i == 0&&i*i==num)
cout << i << '\n';
}
Il n’existe pas de moyen efficace au sens de la complexité algorithmique (un algorithme à complexité polynomiale) connu de la science. Donc, itérer jusqu'à ce que la racine carrée, comme déjà suggéré, soit aussi bon que possible.
C'est principalement pour cette raison qu'une grande partie de la cryptographie actuellement utilisée est basée sur l'hypothèse qu'il est très fastidieux de calculer une factorisation première d'un entier donné.
Voici mon code:
#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();
}
}
La première partie, sieve (), est utilisée pour trouver les nombres premiers et les placer dans le tableau de nombres premiers []. Suivez le lien pour en savoir plus sur ce code (tamis au niveau du bit).
La seconde partie, primeFactors (x) prend un entier (x) en entrée et en découvre les facteurs premiers et l'exposant correspondant, puis les met dans des facteurs vectoriels []. Par exemple, primeFactors (12) va peupler les facteurs [] de la manière suivante:
factors[0].first=2, factors[0].second=2
factors[1].first=3, factors[1].second=1
comme 12 = 2 ^ 2 * 3 ^ 1
La troisième partie, setDivisors (), s’appelle récursivement pour calculer tous les diviseurs de x, en utilisant le vecteur facteurs [] et les met dans des diviseurs vectoriels [].
Il peut calculer les diviseurs de n'importe quel nombre qui convient à int. Aussi c'est assez rapide.
Il existe de nombreuses bonnes solutions pour trouver tous les facteurs premiers de nombres pas trop grands. Je voulais juste souligner qu’une fois que vous les avez, aucun calcul n’est requis pour obtenir tous les facteurs.
si N = p_1^{a}*p_{2}^{b}*p_{3}^{c}.....
Ensuite, le nombre de facteurs est clairement (a+1)(b+1)(c+1)....
puisque chaque facteur peut être zéro jusqu’à un moment.
par exemple. 12 = 2^2*3^1
donc il a 3*2 = 6
facteurs. 1,2,3,4,6,12
======
Au départ, je pensais que vous vouliez simplement connaître le nombre de facteurs distincts. Mais la même logique s'applique. Vous venez de parcourir l'ensemble des nombres correspondant aux combinaisons possibles d'exposants.
donc dans l'exemple ci-dessus:
00
01
10
11
20
21
vous donne les facteurs 6
.
int result_num;
bool flag;
cout << "Number Divisors\n";
for (int number = 1; number <= 35; number++)
{
flag = false;
cout << setw(3) << number << setw(14);
for (int i = 1; i <= number; i++)
{
result_num = number % i;
if (result_num == 0 && flag == true)
{
cout << "," << i;
}
if (result_num == 0 && flag == false)
{
cout << i;
}
flag = true;
}
cout << endl;
}
cout << "Press enter to continue.....";
cin.ignore();
return 0;
}
for (int i = 1; i*i <= num; ++i)
{
if (num % i == 0)
cout << i << endl;
if (num/i!=i)
cout << num/i << endl;
}
//Try this,it can find divisors of verrrrrrrrrry big numbers (pretty efficiently :-))
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<conio.h>
using namespace std;
vector<double> D;
void divs(double N);
double mod(double &n1, double &n2);
void Push(double N);
void show();
int main()
{
double N;
cout << "\n Enter number: "; cin >> N;
divs(N); // find and Push divisors to D
cout << "\n Divisors of "<<N<<": "; show(); // show contents of D (all divisors of N)
_getch(); // used visual studio, if it isn't supported replace it by "getch();"
return(0);
}
void divs(double N)
{
for (double i = 1; i <= sqrt(N); ++i)
{
if (!mod(N, i)) { Push(i); if(i*i!=N) Push(N / i); }
}
}
double mod(double &n1, double &n2)
{
return(((n1/n2)-floor(n1/n2))*n2);
}
void Push(double N)
{
double s = 1, e = D.size(), m = floor((s + e) / 2);
while (s <= e)
{
if (N==D[m-1]) { return; }
else if (N > D[m-1]) { s = m + 1; }
else { e = m - 1; }
m = floor((s + e) / 2);
}
D.insert(D.begin() + m, N);
}
void show()
{
for (double i = 0; i < D.size(); ++i) cout << D[i] << " ";
}
Voici l'implémentation Java de this approche:
public static int countAllFactors(int num)
{
TreeSet<Integer> tree_set = new TreeSet<Integer>();
for (int i = 1; i * i <= num; i+=1)
{
if (num % i == 0)
{
tree_set.add(i);
tree_set.add(num / i);
}
}
System.out.print(tree_set);
return tree_set.size();
}