在C++中使用Eratosthenes的筛子进行素数分解

165 阅读3分钟

今天我们将用埃拉托塞尼斯的筛子来学习素数分解。对于竞技编程来说,与质因数和素数有关的问题是非常常见的。如果你正在学习数据结构和算法课程,那么也应该学习这个概念。首先,我们将通过问题陈述,然后,我们将走向算法和基本概念。所以,让我们开始吧。

问题陈述

给定一个数字作为输入,找出该数字的所有质因数。

比如说。

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);
}

Algorithm 3

算法

使用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;
}

输出

Prime Factorization Using Sieve Output

使用筛子进行素数分解的输出

结论

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