今天我们将用埃拉托塞尼斯的筛子来学习素数分解。对于竞技编程来说,与质因数和素数有关的问题是非常常见的。如果你正在学习数据结构和算法课程,那么也应该学习这个概念。首先,我们将通过问题陈述,然后,我们将走向算法和基本概念。所以,让我们开始吧。
问题陈述
给定一个数字作为输入,找出该数字的所有质因数。
比如说。
Number: 20 = 2 x 2 x 5
Prime Factors: 2, 5
Number: 33 = 3 x 11
Prime Factors: 3, 11
Number: 47 = 1 x 47
Prime Factors: 47(Prime numbers only, 1 is not a prime number)
Number: 100 = 2 x 2 x 5 x 5
Prime Factors: 2, 5
Number: 1200 = 2 x 2 x 2 x 2 x 3 x 5 x 5
Prime Factors: 2, 3, 5
Number: 343 = 7 x 7 x 7
Prime Factors: 7
质因数化的概念
我们可以用多种不同的方法解决这个问题。在这篇文章中,我们将学习使用埃拉托塞尼斯筛的方法来解决这个问题。就时间复杂度而言,Eratosthenes之筛的效率惊人,因为它只需要 O(Nlog2(log2N))个单位的时间。这几乎是线性时间复杂度。以下是我们在编写算法时将遵循的步骤。
- 为了找到一个数字的质因数,我们不需要遍历i = 2到*i = square_root(N)*范围内的所有数字。
- 相反,首先,生成1000000以内的质数列表,然后开始在这个列表上迭代。
- 这种方法使我们避免了许多毫无用处的迭代。
- 初始化一个整数向量来存储质因数。
- 在i = 2到*i = square_root(N)*的范围内运行一个循环。
- 我们运行这个for循环到square_root(N),只是因为一个数字的最大质因数可以是它的平方根。
- 在每次迭代过程中,做以下步骤。
- 如果这个数字能被当前的质数所整除,就整除它的数字,直到它能被整除为止。
- 并将这个素数推到素因子向量中。
- 否则,移到下一个质数。
- 如果这个数字能被当前的质数所整除,就整除它的数字,直到它能被整除为止。
- 一旦你离开了这个循环,检查N的值是否*==1*
- 如果不是,那么N也是一个质数,把N加入因子中。
- 显示该列表并返回。
C++中的素数因数分解算法
void find_prime_factors(vector <int> primes, int N)
{
// initailize the vector
vector <int> factors;
int N_new = N;
int i = 0;
int p = primes[0];
// start the loop
while(p * p <= N_new)
{
if(N % p == 0)
{
factors.push_back(p);
while(N % p == 0)
N /= p;
}
i++;
p = primes[i];
}
// if the number is not 1, then the
// number itself is a prime number
if(N != 1)
factors.push_back(N);
print_factors(factors);
}

算法
使用Eratosthenes的筛子进行素数分解程序
现在让我们来看看使用埃拉托什尼的筛子算法进行素数分解的代码。
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
void prime_sieve(vector <bool> &sieve, int N)
{
// mark address 0 and 1 ans false
// as these are not primes
sieve[0] = sieve[1] = false;
// mark all the even numbers as false
for(int i = 4; i < N; i += 2)
sieve[i] = false;
// now mark the multiples of all
// the odd numbers as false
for(int i = 3; i < N; i += 2)
for(int j = i * i; j < N; j += i)
sieve[j] = false;
}
void store_primes(vector <int> &primes, vector <bool> sieve)
{
primes.push_back(2);
for(int i = 3; i < sieve.size(); i += 2)
if(sieve[i])
primes.push_back(i);
return;
}
void print_factors(vector <int> factors)
{
cout << "The prime factors of the number are:" << endl;
for(int ele : factors)
cout << ele << " ";
cout << endl;
}
void find_prime_factors(vector <int> primes, int N)
{
// initailize the vector
vector <int> factors;
int N_new = N;
int i = 0;
int p = primes[0];
// start the loop
while(p * p <= N_new)
{
if(N % p == 0)
{
factors.push_back(p);
while(N % p == 0)
N /= p;
}
i++;
p = primes[i];
}
// if the number is not 1, then the
// number itself is a prime number
if(N != 1)
factors.push_back(N);
print_factors(factors);
}
int main()
{
int M = 1000;
vector <bool> sieve(M, true);
prime_sieve(sieve, M);
vector <int> primes;
store_primes(primes, sieve);
cout << "Enter the number" << endl;
int N;
cin >> N;
find_prime_factors(primes, N);
return 0;
}
输出

使用筛子进行素数分解的输出
结论
在这篇文章中,我们学习了使用埃拉托什尼的筛子找到一个数字的质因数。我们进一步讨论了这种方法的时间复杂性几乎是线性的。最后,我们编写了算法和一个C++程序来测试它。今天就讲到这里,谢谢大家的阅读。