• 数论-质数专题


    一.判断质数

      思路:任何一个正整数,他的因数一定是成对出现的,如果一个数 x 有除了1和他本身以外的的其他因数,那么一定是一个因数大于根号x, 另一个小于根号x,所以我们可以根据这个性质,来用试除法进行判断是不是质数。

    时间复杂度:O(sqrt(n))

    代码:

    1 bool is_prime(int x)
    2 {
    3     if (x < 2) return false;
    4     for (int i = 2; i <= x / i; i ++ )
    5         if (x % i == 0)
    6             return false;
    7     return true;
    8 }
    View Code

    二.分解质因数

      思路:任何正整数,都可以表示成 X = P1^a * P2^b * .... * Pn^m, 其中P1 P2 Pn都是质数,也就说在自然界中,质数是原子级别的,任何一个数都可以用质数表示,由此可以推出任何一个正整数最多只有一个大于sqrt(x)的质因数(这是一条性质)

    时间复杂度:O(sqrt(n))

    代码:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main(){
     5     int n;
     6     cin >> n;
     7     while(n --){
     8         int a; cin >> a;
     9         //任何一个正整数最多只有一个大于根号a的质因数
    10         for(int i = 2;i <= a / i;++i){
    11             if(a % i == 0){//i 一定是质数, 因为从2到i-1之间没有一个数是a的因数,a又是i的倍数,所以从2到i-1没有一个数是i的因数,所以i是质数
    12                 int s = 0;//i的指数
    13                 while(a % i == 0) a = a / i, ++s;//把i除干净
    14                 cout << i << " " << s << endl;
    15             }
    16         }
    17         if(a > 1) cout << a << " " << 1 << endl;//因为可能有大于根号a的质因数
    18         cout << endl;
    19     }
    20     return 0;
    21 }
    View Code

    三.筛质数

      思路:有三种方法,分别是朴素筛法,埃式筛法,线性筛法

    朴素筛法:

      从2到n枚举每个数 i , 然后把 i 的所有倍数都删掉,如果枚举到某个数p, p没有被删掉,说明从2到p-1之间没有p的因数,所以可以证明p一定是质数,这个算法的缺点是会重复删除,比如, 12,在2的时候删除一次,在3的时候也被删除,由此可见会出现冗余的情况。

    时间复杂度:O(nlog(n))

    代码:

     1 int cnt;
     2 int flag[N], prim[N];
     3 //朴素筛法 O(nlog(log(n)))
     4 void get_prime1(int n){
     5     for(int i = 2;i <= n;++i){
     6         if(!flag[i])//i 没有删除
     7             prim[++cnt] = i;//prim里存的是所有质数
     8         //用来删除当前所有数的倍数
     9         for(int j = i+i;j <= n;j += i)
    10             flag[j] = true;
    11     }
    12 }
    View Code

    埃式筛法:

      和朴素筛法不同的就是删除所有质数的倍数 

    时间复杂度: O(nlog(log(n)))

    代码:

     1 //埃式筛法 O(nlog(log(n)))
     2 void get_prime2(int n){
     3     for(int i = 2;i <= n;++i){
     4         if(!flag[i]){//i 没有删除
     5             prim[++cnt] = i;//prim里存的是所有质数
     6             //用来删除当前所有质数的倍数
     7             for(int j = i+i;j <= n;j += i)
     8                 flag[j] = true;
     9         }
    10     }
    11 }
    View Code

    线性筛法:

      每一个和数都有一个最小质因数,所以我们可以用每一个和数的最小质因数来删除这个和数,所以可知不会重复删除,但是代码不太好理解,背熟

    时间复杂度:O(n)

    代码:

     1 //线性筛法On
     2 void get_prime3(int n){
     3     for(int i = 2;i <= n;++i){
     4         if(!flag[i])prim[++cnt] = i;
     5         for(int j = 1;prim[j] <= n/i;++j){
     6             flag[i*prim[j]] = true;//pj 一定是 i * pj的最小质因数,
     7             if(i % prim[j] == 0)break;
     8         }
     9     }    
    10 }
    View Code
  • 相关阅读:
    【spring 注解驱动开发】spring ioc 原理
    目录大纲,欢迎来戳
    进程相关
    网络编程相关知识点
    Django基本知识
    浅谈 Web框架
    浅谈 Flask 框架
    AJAX小示例
    浅谈cookie 和 session
    ORM:对象关系映射
  • 原文地址:https://www.cnblogs.com/sxq-study/p/12248921.html
Copyright © 2020-2023  润新知