一、试除法求质数
1、思路
想要判断一个数n是否是质数,最暴力的方法是从1到n-1遍历,如果有一个数能将n整除,就代表n不是质数
我们可以发现,对于n来说,n的最大的一个因数不会超过根号n,即i*i<=n。
所以我们只用枚举到根号n即可
时间复杂度为O(根号n)
2、代码模板:
#include<iostream>
using namespace std;
bool su(int x)
{
if(x<2)
return 0;
for(int i=2;i<=x/i;i++)
{
if(x%i==0)
return 0;
}
return 1;
}
int n;
int main()
{
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
if(su(x))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
二、埃氏筛法
1、思路
当我们从小到大遍历到每个数时,直接把这个数的倍数全部筛掉。
时间复杂度为O(nlogn)
对于判断一个数字是否是素数有点慢
这个算法用来判断从1到n的所有质数。
对于朴素法埃氏筛来说,还有个优化版,因为每个合数都能分解为质数的积,所有我们只用把质数的倍数筛掉,这样可以避免一个数被重复筛掉
如6会被2和3重复筛掉。
优化版埃氏筛时间复杂度为O(nloglogn)
比朴素版快了3倍
2、代码模板:
朴素法埃氏筛:
#include<iostream>
using namespace std;
const int N=1e6+10;
int n,cnt;//cnt用来存下标
int primes[N];//记录所有质数
bool st[N];//0代表是质数。1代表不是质数
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
if(!st[i])//如果i是质数
primes[cnt++]=i;
for(int j=1;j<=n/i;j++)
st[i*j]=1;//倍数标记为合数
}
printf("%d",cnt);
return 0;
}
优化版埃氏筛法
#include<iostream>
using namespace std;
const int N=1e6+10;
int n,cnt;//cnt用来存下标
int primes[N];//记录所有质数
bool st[N];//0代表是质数。1代表不是质数
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
if(!st[i])//如果i是质数
{
primes[cnt++]=i;
for(int j=1;j<=n/i;j++)
st[i*j]=1;//倍数标记为合数
}
}
printf("%d",cnt);
return 0;
}
三、线性筛(最快)
1、思路
每一个合数都会被它的最小质因子筛掉。
速度比优化版的埃氏筛快1倍
2、代码模板:
#include<iostream>
using namespace std;
const int N=1e6+10;
int n,cnt;//cnt用来存下标
int primes[N];//记录所有质数
bool st[N];//0代表是质数。1代表不是质数
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
if(!st[i])
primes[cnt++]=i;
for(int j=0;primes[j]<=n/i;j++)
{
st[primes[j]*i]=1;//将质数的倍数标记为合数
if(i%primes[j]==0)//当primes[j]是i的最小质因子时跳出
break;
}
}
printf("%d",cnt);
return 0;
}
四、6倍原理
1、思路
除了2和3,每一个质数,都在6的倍数的左右,
时间复杂度和时除法差不多,比试除法快一点点
2、代码模板:
#include<iostream>
using namespace std;
bool su(int x)
{
if(x<2)
return 0;
if(x==2||x==3)//2,3特判
return 1;
if(x%6!=1&&x%6!=5)//当x不为6左右两边的数时就不是质数
return 0;
for(int i=5;i<=x/i;i+=6)
{
if(x%i==0||x%(i+2)==0)
return 0;
}
return 1;
}
int n;
int main()
{
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
if(su(x))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
五、分解质因数
1、原理
和试除法差不多,每次遇到质因数就一直除直到不能整除再换下一个
时间复杂度为O(根号n)
n最多有一个大于根号n的质因子。
2、代码模板:
#include<iostream>
using namespace std;
int n;
int main()
{
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
for(int i=2;i<=x/i;i++)
{
int sum=0;
if(x%i==0)
{
while(x%i==0)
{
x/=i;
sum++;
}
printf("%d %d\n",i,sum);
}
}
if(x>1)
printf("%d 1\n",x);
printf("\n");
}
return 0;
}

京公网安备 11010502036488号