试除法判定质数
质数定义:一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数,这个数就是质数。
一个数的因数都是成对出现的,1 和 n 是一对因数,所以从2开始枚举
x <= n/x x * x <= n x <= 根号n
可以用 n 除以[ 2,根号n ] 中的每个数,如果余数为 0不是质数,如果没出现余数为 0,则是质数。
i 就是 从 2 到 根号n 遍历
int sovle()
{
ll n, i;
cin >> n;
if(n < 2)
return 0;
for(i = 2; i <= n / i; i ++)
if(n % i == 0)
return 0;
return 1;
}
分解质因数
if(a % i == 0) 中的 i 一定是质数,合数能被分成多个质因数
n中最多只含有一个大于sqrt(n)的因子,可以先枚举不大于sqrt(n)的因子
每个大于1的数都可以分解为他自身和1的乘积,最后判断>1是否有多余的因子
n = 252 = 2^2 * 3^2 * 7
第一次循环结束 i = 3,n = 63
第二次循环结束 i = 4,n = 7
第三次循环判断 4 <= 7 / 4
当枚举到 i 的时候,已经把 [2,i - 1 ]中的质因子都除干净了所以 n = 7 里的质因子不可能有[ 2,i - 1 ],所以从4开始
#include<iostream>
#include<algorithm>
using namespace std;
int main(void)
{
int n;cin>>n;
while(n--)
{
int a;cin>>a;
for(int i=2;i<=a/i;i++)
{
if(a%i==0)
{
int s=0;
while(a%i==0)
{
a/=i;
s++;
}
cout<<i<<" "<<s<<endl;
}
}
if(a>1) cout<<a<<' '<<1<<endl;
cout<<endl;
}
return 0;
}
筛质数
诶氏筛法
如果P没有被筛掉,那么P 就不是 [2,P - 1] 中任何数的倍数,所以P是质数
sovle()
{
for(int i = 2; i <= n; i ++)
if(! st[i])
{
primes[cnt ++] = i;
//把质数的倍数删掉,多个质数的和为合数
for(int j = i + i; j <= n; j ++)
st[j] = true;
}
//for(int j = i + i; j <= n; j ++)循环可以放里面
}
线性筛法
n只会被最小质因子筛掉
sovle()
{
for(int i = 2; i <= n; i ++)
{
if(!st[i])
primes[cnt ++] = i;
for(int j = 0; primes[j] <= n / i; j ++) //primes[j] * i <= n
{
st[primes[j] * i] = true; //用最小质因子去筛合数
if(i % primes[j] == 0)
break;
/*
n = 12 primes[] = 2, 3, 5, 7, 11
i = 2 把 2 * i 筛掉,2是i的最小质因子break
i = 3 把 2 * i 筛掉,2不是i的最小质因子,继续
把 3 * i 筛掉,3是i的最小质因子break
i = 4 把 2 * i 筛掉,4是i的最小质因子break
i = 5 把 2 * i 筛掉,5不是i的最小质因子,继续
3 * i > n , 结束
*/
}
}
}
p[ ] =[2,3,5,7]
当 i = 7 % p[ j ] != 0时,p[ j ] 并不是 i 的最小质因子,所以它的最小质因子肯定比2还大,p[ j ]已经是质数,那么 p[ j ] 一定是 p[ j ] * i 的最小质因子
j 循环每次都把 p[ j ] 的 i 倍筛掉
条件:p[ j ] * i <= n
结束:i % primes[ j ] == 0
1、当 i % p[ j ] != 0 时,说明p[ j ]不是 i 的最小质因子,因此 p[ j ] 一定是 p[ j ] * i 的最小质因子
2、当 i % primes[j] == 0 时,说明i的最小质因子是[ j ],p[ j ] * i 的最小质因子也是p[ j ],结束避免重复
所以,p[ j ] 一定是 p[ j ] * i 的最小质因子,st[p[ j ] * i] = true;