C/C++快速求素数【细节满满】

个人主页:仍有未知等待探索_C语言疑难,数据结构,小项目-CSDN博客

专题分栏:数论_仍有未知等待探索的博客-CSDN博客

目录

 

一、暴力求解

1、求1-n之间的素数(O(n^2))

1.思路

2.代码 

 2、判断某个数x是否为素数

1.思路

2.代码

二、 Eratosthenes筛法(埃氏筛)

1、求1-n之间的素数(O(n^logn))

1.思路

2.代码

三、 Euler 筛法(欧拉筛法)

1、求1-n之间的素数(O(n))

1.思路

2.代码


 

一、暴力求解

在以前的学习的时候,我们写过如何求1-n以内的素数,也写过判断某个数是否是素数。我们学过素数(也称质数)只能被1和它本身的整除。

根据这个,我们可以开始写了。

1、求1-n之间的素数(O(n^2))

1.思路

首先,我们要有1-n之间的数,然后一个一个的判断其是不是素数,然后进行打印。

根据下面的代码或者这个思路,我们可以知道这个代码的时间复杂度为O(n^2)。在一些比赛中,可能会被卡时间。

因为我们知道1不是素数,所以提供的数从2开始。

2.代码 

#define _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h>
#include<math.h>
void _prime(int n);
int main()
{
	int n;
	scanf("%d", &n);
	_prime(n);
	return 0;
}
void _prime(int n)
{
	//因为我们知道1不是素数,所以直接从2开始进行判断
	for (int i = 2; i <= n; i++)
	{
		//判断是否是素数
		int flag = 0;
		for (int j = 2; j <= sqrt(i); j++)
		{
			if (i % j == 0)
			{
				flag = 1;
				break;
			}
		}
		if (flag == 0)
		{
			printf("%d ", i);
		}
	}
}

 2、判断某个数x是否为素数

1.思路

循环2-sqrt(x),然后对x进行取余,如果取余结果为0,则不是素数,反之,是素数。

2.代码

#include<stdio.h>
#include<math.h>
int isprime(int x);
int main()
{
	int x;
	scanf("%d", &x);
	if (isprime(x) == 1)
	{
		printf("YES\n");
	}
	else
	{
		printf("NO\n");
	}
	return 0;
}
int isprime(int x)
{
	if (x == 1)
		return 0;
	for (int i = 2; i <= sqrt(x); i++)
	{
		if (x % i == 0)
			return 0;
	}
	return 1;
}

二、 Eratosthenes筛法(埃氏筛)

1、求1-n之间的素数(O(n^logn))

1.思路

这个筛法的思路是把所有质数的整数倍全部筛掉。

同样地,我们首先是提供1-n之间的数。然后判断数是不是素数,如果是素数,将素数的整数倍都标记成不是素数。如果不是素数,则不做处理。这样的话,会减少其时间复杂度,但仍然会重复定义。

其时间复杂度是O(n*logn),虽然减少了一点儿,可还是有一些长。

判断是不是素数,不要写一个判断函数,从2-sqrt(n)进行循环取余判断。

我们先设立一个数组,用来标记素数。然后我们将数组中全部默认标记为是素数。

然后我们从数字2(我们知道数字2是素数)开始进行对其整数倍进行标记,同理3也是如此。这样就可以将素数进行标记出来。

因为我们知道1不是素数,所以提供的数从2开始。

2.代码

#include<stdio.h>
#define MAX 100
int prime[MAX];//记录素数,默认2-n之间全是素数,然后再进行筛选
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 2; i <= n; i++)
	{
		//因为我们知道1不是素数,所以直接从2开始进行判断
		if (prime[i] == 0)
		{
			for (int j = 2 * i; j <= n;j+=i)
			{
				//0代表素数,1代表非素数
				prime[j] = 1;
			}
		}
	}
	for (int i = 2; i <= n; i++)
	{
		if (prime[i] == 0)
			printf("%d ", i);
	}
	return 0;
}

三、 Euler 法(欧拉筛法)

1、求1-n之间的素数(O(n))

1.思路

欧拉筛是唯一筛掉一个数的筛法,不存在重复计算,所以时间复杂度是O(n)。

核心代码:i % prime[j] == 0(i是素数的倍数)。

2.代码

#include<stdio.h>
#define MAX 100
int prime[MAX];//用来记录素数,0为素数
int record[MAX];
int cnt;//记录素数的大小
void Euler(int n);
int main()
{
	int n;
	scanf("%d", &n);
	Euler(n);
	for (int j = 0; j < cnt; j++)
	{
		printf("%d ", prime[j]);
	}
	return 0;
}
void Euler(int n)
{
	for (int i = 2; i <= n; i++)
	{
		if (!record[i])//如果当前是素数,记录下来
		{
			prime[cnt++] = i;
		}
		for (int j = 0; j < cnt && i * prime[j] <= n; j++)
		{
			record[i * prime[j]] = 1;
			if (i % prime[j] == 0)
				break;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_73435980/article/details/134210427