参考自该篇博客https://www.cnblogs.com/grubbyskyer/p/3852421.html;
参考自该篇博客https://blog.csdn.net/liamleec/article/details/78524039
个人理解:
暴搜法:
其分为两种,一种是直接for循环,另一种是建立在数学思想上的平方根循环。第二种算法时间复杂度明显优于第一种。
1、暴力法:O(n*n)
也就是最简单直接的for循环,判定这个数是否能被除1 和其本身以外的整数整除。
2、sqrt(n)暴搜: O(n*sqrt(n))
这个也是基于for循环的一种方式,比上面那种方法稍微快了一点。当n的数值较大时,程序运行时间也比较长。原理:一个数只能被1和其本身整除,这样的数称为素数反之,不满足这个条件的即为非素数。
假定非素数num,一定能分解为两个整数的乘积,n和m,num = n * m;若n,m都大于sqrt(num),则不成立;所以,n和m中一定有一个小于等于sqrt(num)。换句话说,如果不存在这样的一个小于sqrt(num)的整数,则num就为素数。
代码:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int i,n, x;
cin >> n;
x = sqrt(n);
for (i = 2; i <= x; i++)
if (n % i == 0)
break; //跳出本层循环
if (i > x) //找出小于sqrt(n)的整数
cout << "Yes!"; //若无,则为素数,
else
cout << "No!"; //若存在,为非素数
return 0;
}
筛选素数法:
1, 普通筛选法——埃拉托斯特尼(Eratosthenes)筛选法:O(n*loglogn)
要求n以内的素数,我们可以先构建一个大小为n+1的bool类型数组,并将各元素初始化为true(true表示为素数,false表示非素数),再通过算法将素数的下标所对应元素值赋为true,最后输出所有为true元素的下标即可。
用一个长度为n+1的数组保存信息(true表示素数,false表示非素数),先假设所有的数都是素数(初始化为true),从第一个素数2开始,把2的倍数都标记为非素数(置为false),一直到大于n;然后进行下一趟,找到2后面的下一个素数3,进行同样的处理,直到最后,数组中依然为true的数即为素数,遍历输出即可。
代码:
#include<iostream>
#include<algorithm>
#include<cstdbool>
using namespace std;
# define N 1024
int main()
{
int tot = 0;
bool num[N];
memset(num, true, sizeof(num)); //初始化
for (int i = 2; i < sqrt(N); i++)
{
if (num[i])
{
for (int j = 2; j * i < N; j ++)
{
num[j * i] = false;
}
}
}
for (int i = 2; i < N; i++)
{
if (num[i])
cout << i << " ";
}
return 0;
}
2,二次筛选法:O(n*loglogn)
是普通筛选法算法的改进。
代码:
#include<iostream>
#include<algorithm>
#include<cstdbool>
using namespace std;
# define N 1024
int main()
{
int tot = 0;
bool num[N];
memset(num, true, sizeof(num)); //初始化
for (int i = 2; i < sqrt(N); i++)
{
if (num[i])
{
for (int j = i * i; j < N; j += i)
{
num[j] = false; //二次筛选法:i是素数,则下一个起点是i*i,把后面的所有的i*i+2*n*i筛掉
}
}
}
for (int i = 2; i < N; i++)
{
if (num[i])
cout << i << " ";
}
return 0;
}
3,线性筛选法:O(n)
在普通筛选法的基础之上进行最大程度的优化。普通筛选法在提高运行效率的同时也有缺点,就是很多数被处理了不止1遍,因此又造成了比较大的不必要处理。比如说非素数6,以2进行筛选时筛选了一次,以3进行筛选,又筛选了一次,线性筛选素数就是一个非素数以最小质因数筛选一次即可。
代码:
#include<iostream>
#include<algorithm>
#include<cstdbool>
using namespace std;
# define N 1024
int main()
{
int tot = 0;
bool num[N]; //判定是否为素数
int prime[N]; //素数集合
memset(num, true, sizeof(num)); //初始化
for (int i = 2; i < N; i++)
{
if (num[i])
prime[tot++] = i;
for (int j = 0; j < tot && prime[j] * i < N; j++)
{
num[prime[j] * i] = false;
if (i % prime[j] == 0)
break;
}
}
for (int i = 2; i < N; i++)
{
if (num[i])
cout << i << " ";
}
return 0;
}