2024-02-02(数论-质数、约数)

1.质数

在大于1的整数中,如果只包含1和它本身这两个约数,就称为质数或者素数。

(1)试除法判定质数 

866. 试除法判定质数 - AcWing题库

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

import java.util.Scanner;

public class Main{
    public static void is_prime(int a){
        if(a < 2){
            System.out.println("No");//注意这里测试数据是从1开始的,所以要加上一个判断
            return;
        }
        for(int i = 2; i <= a / i; i ++){//i<= a/i这种写法比较好,其它的可能会溢出或者效率低什么的
            if(a % i == 0){
                System.out.println("No");
                return;
            }
        }
        System.out.println("Yes");
        return;
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while(n -- > 0){
            int a = sc.nextInt();
            is_prime(a);
        }
    }
}

(2)分解质因数(试除法)

867. 分解质因数 - AcWing题库

1. 时间复杂度为O(sqrt(n)) 

2. n中最多只包含一个大于sqrt(n)的质因子

import java.util.*;

public class Main{
    public static 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 ++;
                }
                System.out.println(i + " " + s);
            }
        }
        //一个数n最多只有一个大于sqrt(n)的质因子
        //如果n>1,说明n就是那个质因子
        if(n > 1) System.out.println(n + " 1");
        System.out.println();
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while(n -- > 0){
            int a = sc.nextInt();
            divide(a);
        }
    }
}

(3)筛质数(朴素,埃氏,线性)

868. 筛质数 - AcWing题库

朴素法O(nlogn)   

埃氏筛 O(nloglogn)  

线性筛(欧拉筛)O(n)

import java.util.*;

public class Main{
    static int N = 1000010, cnt, n;
    static int[] pr = new int[N];
    static boolean[] st = new boolean[N];
    
    //朴素法
    public static void find(int x){
        for(int i = 2; i <= n; i ++){
            if(!st[i]) pr[cnt ++] = i;
            for(int j = i + i; j <= n; j += i){
                st[j] = true;
            }
        }
    }
    
    //埃氏法
    public static void find1(int x){
        for(int i = 2; i <= x; i ++){
            if(!st[i]){
                pr[cnt ++] = i;
                for(int j = i + i; j <= n; j += i){
                    st[j] = true;
                }
            }
        }
    }
    
    //欧拉法(线性)
    //每个n只会被它的最小质因子筛掉
    //每个数只有一个最小质因子,所以每个数只会被筛一次,不会重复筛
    public static void find2(int x){
        for(int i = 2; i <= x; i ++){
            if(!st[i]) pr[cnt ++] = i;
            for(int j = 0; pr[j] <= n / i; j ++){
                st[pr[j] * i] = true;
                if(i % pr[j] == 0) break;//pr[j]一定是i的最小质因子
            }
        }
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        find2(n);
        System.out.print(cnt);
    }
}

2.约数

(1)试除法求一个数的所有约数

869. 试除法求约数 - AcWing题库

1.  Java的集合排序:Collections.sort、list.sort和list.stream().sorted方法详解-CSDN博客  

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while(n -- > 0){
            int a = sc.nextInt();
            find(a);
        }
    }
    
    public static void find(int a){
        ArrayList<Integer> list = new ArrayList<>();
        for(int i = 1; i <= a / i; i ++){//遍历一对约数中较小的那个
            if(a % i == 0){
               list.add(i);//把较小的那个约数放进容器
                if(i != a / i) list.add(a / i);//特判,如果这一对彼此不相等,那么都放进去
            }
        }
        //时间复杂度为O(nlogn)
        Collections.sort(list);//题目说要从小到大,所以要排下序
        for(int i:list){
            System.out.print(i + " ");
        }
        System.out.println();
    }
}

(2)约数的个数

870. 约数个数 - AcWing题库

1.    求约数个数(公式、原理以及Java代码实现)_java约数-CSDN博客

2,Java HashMap getOrDefault() 方法 | 菜鸟教程 (runoob.com) 

公式   (a1+1)*(a2+1)*(a3+1)*...*(ak+1) 

import java.util.*;

public class Main{
    static int mod = (int)1e9 + 7;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Integer, Integer> map = new HashMap<>();//构造一个哈希表
        
        //以下是用了分解质因数的模板
        while(n -- > 0){
            int x = sc.nextInt();
            for(int i = 2; i <= x / i; i ++){
                while(x % i == 0){
                    x /= i;
                    map.put(i, map.getOrDefault(i, 0) + 1);
                }
            }
            if(x > 1) map.put(x, map.getOrDefault(x, 0) + 1);
        }
        
        long res = 1;
        for(int key: map.values()){
            res = res * (key + 1) % mod;//这里不可以写成 res *= (key + 1) % mod
        }
        System.out.print(res);
    }
}

(3)约数之和

871. 约数之和 - AcWing题库

1、 约数之和 - Y2ZH - 博客园 (cnblogs.com)

2、Java的Map中的map.keySet()方法-CSDN博客 

import java.util.*;

public class Main{
    static int mod = (int)1e9 + 7;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Integer, Integer> map = new HashMap<>();
        while(n -- > 0){
            int x = sc.nextInt();
            for(int i = 2; i <= x / i; i ++){
                while(x % i == 0){
                    x /= i;
                    map.put(i, map.getOrDefault(i, 0) + 1);
                }
            }
            if(x > 1) map.put(x, map.getOrDefault(x, 0) + 1);
        }
        long res = 1;
        for(int a : map.keySet()){
            int b = map.get(a);
            long t = 1;
            while(b -- > 0){
                t = (t * a + 1) % mod;//这里加1是因为b-->0没有算到0次方,所以要加上1
            }
            // p = a ^ 3 * b ^ 1;
           // sum = (a ^ 0 + a ^ 1 + a ^ 2 + a ^ 3) * (b ^ 0 + b ^ 1)
            res = res * t % mod;
        }
        System.out.print(res);
    }
}

(4)求最大公约数(欧几里得算法-辗转相除法)

 872. 最大公约数 - AcWing题库

 

import java.util.*;

public class Main{
    public static int gcd(int a, int b){
        return b > 0? gcd(b, a % b) : a;//辗转相除法
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while(n -- > 0){
            int a = sc.nextInt();
            int b = sc.nextInt();
            System.out.println(gcd(a, b));
        }
    }
}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值