质数

质数
1.什么叫质数?
在大于1的整数中,只包含1和本身两个约数,叫做质数或素数。

2.质数的判定 - 试除法,O(sqrt(n))
循环中i < n / i,因为假如12,4 和 3 是约数,既然 4 是那么 3 也是,所以我们只需判断一个。
不要写成 i < sqrt ( n ), 这个判断比较慢,i * i < n 也不要,因为i * i 可能会越界。

3.分解质因数 - 试除法,O(sqrt(n)) 但是不一定是这个,最好是logn

  • 从小到大枚举所有的,比如:28 的质因数
    首先 ,28的因子从小到大为 2,4,7,14
    28 / 2 =14;
    14 / 2 = 7;
    7 / 7 = 1; (这里最后一步的结束条件是得到的数 1 % 7(因数)!= 0)
void divide(int n)
{
    for(int i = 2;i <= n;i++)
    {
        if(n % i == 0)
        {
            int s = 0;
            while(n % i ==0)
            {
                n /= i;
                s ++;
            }
            printf ("%d %d\n", i,s);
        }
    }
  • 优化:n当中最多只包含一个大于根号n的质因子,单独处理,最后大于1,剩下的就是它
void divide(int n)
{
    for(int i = 2;i <= n / i;i++)
    {
        if(n % i == 0)
        {
            int s = 0;
            while(n % i ==0)
            {
                n /= i;
                s ++;
            }
            printf ("%d %d\n", i,s);
        }
      if(n > 1)  printf ("%d\n", n);
    }

4.筛质数

  • 比如2 3 4 5 6 7 8 9 10 11 12,把每个数的倍数筛掉,就剩3 5 7 9 11 O(ln n)
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int primes[N],cnt;
bool st[N];
void get_prime(int n)
{
    for(int i = 2;i <= n;i++)
    {
        if(!st[i])    //没有被筛掉就放进primes
            primes[cnt++] = n;
        for(int j = i + i;j <= n;j += i) //筛掉倍数
            st[j] = true;
    }
}
int main()
{
    int n;
    cin>>n;
    get_prime(n);
    cout<<cnt<<endl;
    return 0;
}
  • 优化,埃式筛法,筛掉质数的倍数,不是质数就不需要,质数定理:1到n中有n / ln n 个质数 O(n * log (log n))
    一个合数可以表示成一个质数与一个数的乘积。
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int primes[N],cnt;
bool st[N];
void get_prime(int n)
{
    for(int i = 2;i <= n;i++)
    {
        if(!st[i])    //没有被筛掉就放进primes
        {
            primes[cnt++] = n;
        for(int j = i + i;j <= n;j += i) //筛掉倍数,放到里边
            st[j] = true;
        }
    }
}
int main()
{
    int n;
    cin>>n;
    get_prime(n);
    cout<<cnt<<endl;
    return 0;
}
  • 线性筛法:使每个数只被自己的最小质因数筛掉,也就是只筛一次,不会重复,对埃式算法的优化,在这个程序中,不是质数就不会进入primes,并且保证只被自己的最小质因数筛掉,如果这个数n能被primes里的一个数整除,那么就找到自己的最小质因数了,然后就break。
    i % primes[j] == 0,那么primes[j]是i的最小质因子,primes[j]也是i * primes[j]的最小质因子
    i % primes[j] != 0,那么primes[j]比i的最小质因子小,primes[j]还是i * primes[j]的最小质因子
    所以保证只被自己的最小质因数筛掉。
    O( n )
void get_prime(int 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] = true;
            if(i % primes[j] == 0)
                break;
    }
}
posted @ 2022-10-27 22:44  焦糖玛奇果  阅读(1432)  评论(0)    收藏  举报