数论求质数(素数)

质数定义:在大于1的整数中,如果只包含1和本身这两个约数,就被成为质数,或者叫素数。

质数的判定——试除法

从1到n循环判断是否能被整除,如果能被整除说明n不是质数,不能被整除说明是质数。
因为每个除数都是成对出现的,比如 12 = 2 × 6 12=2 \times 6 12=2×6 12 = 3 × 4 12=3 \times 4 12=3×4,2和4对应,3和6对应,分别是一个大于 12 \sqrt{12} 12 ,一个小于 12 \sqrt{12} 12 ,12能够被2整除那么一定也可以被6整除,所以可以让循环判断的范围从1到n缩小到1到 n \sqrt{n} n

试除法的时间复杂度是 O ( s q r t ( n ) ) O(sqrt(n)) O(sqrt(n))
数论求质数(素数)_第1张图片

import java.io.*;

public class Main{
    public static void main(String[] args)throws IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(in.readLine());
        for(int i=0;i<n;i++){
            int a=Integer.parseInt(in.readLine());
            boolean flag=scf(a);
            if(flag)System.out.println("Yes");
            else System.out.println("No");
        }
    }
    static boolean scf(int n){
        if(n<2)return false;
        for(int i=2;i<=n/i;i++){
            if(n%i==0)return false;
        }
        return true;
    }
}

分解质因数——试除法

利用试除法从1到n遍历,计算相应质因数的个数,因为循环是从小到大遍历的缘故,所以不会存在质因数是合数的情况。比如循环遍历到4时,不会计算4这个不是质数的因素,因为n中的2已经被除完了。
因为n只存在一个大于 n \sqrt{n} n 的质因数,所以,循环可以从1到n缩减到1到 n \sqrt{n} n ,然后在循环外特判以下就好了。比如 110 = 2 × 5 × 11 110=2 \times 5 \times 11 110=2×5×11,如果 11 × 11 = 121 11 \times 11=121 11×11=121就超出110的范围了。
数论求质数(素数)_第2张图片

import java.io.*;

public class Main{
    public static void main(String[] args)throws IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(in.readLine());
        for(int i=0;i<n;i++){
            int a=Integer.parseInt(in.readLine());
            scf(a);
            System.out.println();
        }
    }
    static void scf(int n){
        for(int i=2;i<=n/i;i++){
            if(n%i==0){
                int s=0;
                while(n%i==0){
                    n/=i;
                    s++;
                }
                System.out.println(i+" "+s);
            }
        }
        if(n>1)System.out.println(n+" "+1);
    }
}

筛法求质数

数论求质数(素数)_第3张图片

普通筛法

数论求质数(素数)_第4张图片
如上图所示:
从左到右筛除相应非质数。

import java.io.*;

public class Main{
    static int N=1000010;
    static boolean[] st=new boolean[N];
    static int[] primes=new int[N];
    static int cnt;
    public static void main(String[] args)throws IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(in.readLine());
        assf(n);
    }
    static void assf(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;
        }
        System.out.println(cnt);
    }
}

埃式筛法

数论求质数(素数)_第5张图片
如上图所示:
当为质数时才进行后续的相应筛除

import java.io.*;

public class Main{
    static int N=1000010;
    static boolean[] st=new boolean[N];
    static int[] primes=new int[N];
    static int cnt;
    public static void main(String[] args)throws IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(in.readLine());
        assf(n);
    }
    static void assf(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;
            }
        }
        System.out.println(cnt);
    }
}

线性筛法

数论求质数(素数)_第6张图片
每次都是用被筛除掉的数的最小质因子将其筛除的

i i i % p j = = 0 : p_j==0: pj==0:因为 i , j i,j i,j是从小到大枚举的,所以 p j p_j pj一定是 i i i的最小质因子, p j p_j pj一定是 p j × i p_j \times i pj×i的最小质因子
i i i % p j ! = 0 : p j p_j!=0:p_j pj!=0:pj一定小于 i i i的所有质因子, p j p_j pj也一定是 p j × i p_j \times i pj×i的最小质因子

import java.io.*;

public class Main{
    static int N=1000010;
    static boolean[] st=new boolean[N];
    static int[] primes=new int[N];
    static int cnt;
    public static void main(String[] args)throws IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(in.readLine());
        xxsf(n);
    }
    static void xxsf(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;
            }
        }
        System.out.println(cnt);
    }
}

你可能感兴趣的:(算法学习,java,算法)