接下来的几篇文章主要用来讲解数学知识,这个数学可谓是很重要的,不论是算法竞赛还是找工作面试,这个数学知识还是会经常考的,主要考察你的思维能力。本文主要介绍了质数的概念、判定、分解质因数、筛质数,然后那就开始吧。
在大于1的自然数中,只包含1和它本身这两个约数,就叫质数,也叫素数(这两个是一个东西,叫法不一样而已)
算数基本定理:每一个大于1的自然数N都可以写成
N
=
p
1
α
1
?
p
2
α
2
?
p
3
α
3
?
?
?
p
k
α
k
,
p
i
为质数
N = p_{1}^{\alpha_{1}} \cdot p_{2}^{\alpha_{2}} \cdot p_{3}^{\alpha_{3}} \cdot \cdots \cdot p_{k}^{\alpha_{k}},p_{i}为质数
N=p1α1???p2α2???p3α3?????pkαk??,pi?为质数
一般是从2到n-1遍历,只要n%i==0,那就说明不是质数
但可以从2~sqrt(n),因为如果n为约数,那么它的约数数量肯定是一个偶数,是成对出现的,所以我们只要枚举每对约数中较小的那个就可以判断了。
当然你可以拿sqrt(n)来给一个 t 赋值,不能每次都计算sqrt不然就会很慢
或者可以直接拿i <= n / i,因为如果 n 是约数的话,i 和 n / i 都能被n整除,那么我们枚举的都是较小的,所以一定i <= n / i的,时间复杂度降为
O
(
N
)
O(\sqrt{N})
O(N?)
bool isPrime(int n)
{
if(n < 2) return false;
for(int i = 2; i <= n / i; ++i)
{
if(n % i == 0) return false;
}
return true;
}
本来是从2-n遍历的,但是由于一个数中大于 n \sqrt{n} n?的约数只有一个,所以可以先从 n \sqrt{n} n? 最后再判断一下就可以了,时间复杂度降到了 O ( N ) O(\sqrt{N}) O(N?)
void divide(int n)
{
for(int i = 2; i <= n / i; ++i)
{
int s = 0;
if(n % i == 0)
{
while(n % i == 0) s++,n /= i;
printf("%d %d\n", i, s);
}
}
if(n > 1) printf("%d %d\n", n, 1);
puts("");
}
题目描述:
给定一个正整数 n,请你求出 1~n 中质数的个数。
输入格式
共一行,包含整数 n。
输出格式
共一行,包含一个整数,表示 1~n 中质数的个数。
数据范围
1≤n≤106
输入样例:
8
输出样例:
4
思想:根据算术基本定理,用质数把每一个质数的倍数筛掉就可以了,时间复杂度: O ( N log ? log ? N ) O(N\log{\log{N}}) O(NloglogN)
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1e6+10;
int primes[N], cnt;
bool st[N];
int get_primes(int n)
{
for(int i = 2; i <= n; ++i)
{
if(!st[i])
{
primes[cnt++] = i;
for(int j = i + i; j <= n; j += i) st[j] = true;
}
}
}
int main()
{
int n;
cin >> n;
get_primes(n);
printf("%d\n", cnt);
return 0;
}
思想:每一个约数只会被它的最小质因子筛掉,时间复杂度 O ( N ) O(N) O(N)
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1e6+10;
int primes[N], cnt;
bool st[N];
int get_primes(int n)
{
for(int i = 2; i <= n; ++i)
{
if(!st[i]) primes[cnt++] = i;
for(int j = 0; primes[j] * i <= n; ++j)
{
st[primes[j] * i] = true;
if(i % primes[j] == 0) break; // primes[j]一定是i的最小质因子
}
}
}
int main()
{
int n;
cin >> n;
get_primes(n);
printf("%d\n", cnt);
return 0;
}