判断是不是质数
质数的判定------试除法 O ( n ) O(\sqrt{n}) O(n), 其 实 是 [ l o g n , n ] 其实是[logn,\sqrt{n}] 其实是[logn,n]
for循环里面的判断条件一定要写成for(int i = 2; i <= a / i; ++i),如果是i*i<=a,那么对于判断较大的数的时候会溢出
核心代码:
bool isPrime()
{
if(a < 2)
return false;
for(int i = 2; i <= a / i; ++i)
if(a % i == 0)
return false;
return true;
}
分解质因数------试除法 O ( n ) O(\sqrt{n}) O(n)
从小到大枚举尝试所有n的因数,也只需要枚举到 n \sqrt{n} n就行了
n n n 中最多只包含一个大于 n \sqrt{n} n的质因子。反证法:如果有两个,乘起来就大于了 n n n
n
=
p
1
a
1
∗
p
2
a
2
∗
p
3
a
3
.
.
.
.
.
p
n
a
n
n=p_1^{a_1} * p_2^{a_2} *p_3^{a_3}.....p_n^{an}
n=p1a1∗p2a2∗p3a3.....pnan
注意退出
f
o
r
for
for 循环之后,
a
a
a 可能大于
1
1
1 ,因为可能存在一个大于
n
\sqrt{n}
n 的质因数,比如
21
=
3
∗
7
21=3*7
21=3∗7
核心代码如下:
void output()
{
for(int i = 2; i <= a/i; ++i)
{
if(a % i == 0)
{
int s = 0;
while(a % i == 0)
{
a /= i;
++s;
}
printf("%d %d\n", i, s);
}
}
if(a>1)//n当中最多只包含一个大于根号n的质因子
printf("%d %d\n",a,1);
}
筛质数
朴素筛法 O ( n l o g n ) O(nlogn) O(nlogn)
筛掉所有数的倍数
int n,st[MAXN],prime[MAXN],cnt;
void get_prime()
{
for(int i=2;i<=n;++i)
{
if(!st[i])
{
prime[cnt++]=i;
st[i]=true;
}
for(int j=i*2;j<=n;j+=i)
st[j]=true;
}
}
埃及氏筛法 O ( n l o g l o g n ) O(nloglogn) O(nloglogn)
筛掉所有质数的倍数
质数定理: 1 − n 1-n 1−n 中的质数个数是 n l n n \frac{n}{lnn} lnnn
st数组用来保存当前这个数是否被筛掉,prime数组用来存储素数,与朴素筛法的区别就是把for放进了if里面
int n,st[MAXN],prime[MAXN],cnt;
void get_prime()
{
for(int i=2;i<=n;++i)
{
if(!st[i])
{
prime[cnt++]=i;
st[i]=true;
for(int j=i*2;j<=n;j+=i)
st[j]=true;
}
}
}
线性筛法 O ( n ) O(n) O(n)
核心:一个数 n n n 只会它他的最小质因子筛掉,每个数只有一个最小质因子,所以是线性的
情况
1
1
1 :当
i
%
p
r
i
m
e
[
j
]
=
=
0
i\%prime[j]==0
i%prime[j]==0 时,
p
r
i
m
e
[
j
]
prime[j]
prime[j] 一定是i的最小质因子,那么
p
r
i
m
e
[
j
]
prime[j]
prime[j] 也一定是
p
r
i
m
e
[
j
]
∗
i
prime[j]*i
prime[j]∗i 的最小质因子
情况
2
2
2 :当
i
%
p
r
i
m
e
[
j
]
!
=
0
i\%prime[j]!=0
i%prime[j]!=0 时,
p
r
i
m
e
[
j
]
prime[j]
prime[j] 一定小于i的最小质因子,所以
p
r
i
m
e
[
j
]
prime[j]
prime[j] 也一定是
p
r
i
m
e
[
j
]
∗
i
prime[j]*i
prime[j]∗i 的最小质因子
for(int i = 2; i <= n; ++i)
{
if(!st[i])//如果这个数是质数,把他加到primes集合里面去
primes[cnt++] = i;
for(int j = 0; primes[j] <= n / i; ++j)//保证每个数都只被他的最小质因子筛掉,之所以要<=n/i,是因为保证下面的st不越界
{
st[primes[j] * i] = true;//不管pirmes[j]这个数是否能整除i,primes[j]*i这个数的最小质因子一定是primes[j]
if(i % primes[j] == 0)//这里之所以要break掉,是因为如果不break就不能保证下一次primes[j]是primes[j]*i的最小质因子,这样就多算了
break;
}
}