个人主页:仍有未知等待探索_C语言疑难,数据结构,小项目-****博客
专题分栏:数论_仍有未知等待探索的博客-****博客
目录
一、暴力求解
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<>
#include<>
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<>
#include<>
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<>
#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<>
#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;
}
}
}