2024-02-03(欧拉函数,快速幂,扩展欧几里得算法,中国剩余定理)

1.欧拉函数

(1)欧拉函数

 欧拉函数:1~n中与n互质的数的个数

互质:两个数的公约数只有1

873. 欧拉函数 - AcWing题库

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 x = sc.nextInt();
            int res = x;
            for(int i = 2; i <= x / i; i ++){//分解质因数的模板
                if(x % i == 0){
                    res = res / i * (i - 1);//欧拉函数的公式,先除再乘防止溢出
                }
                while(x % i == 0){
                    x /= i;
                }
            }
            if(x > 1) res = res / x * (x - 1);
            System.out.println(res);
        }
    }
}

(2)筛法求欧拉函数 

 874. 筛法求欧拉函数 - AcWing题库

质数i的欧拉函数即为phi[i] = i - 1 

import java.util.*;

public class Main{
    static int N = 1000010;
    static int[] phi = new int[N];
    static int[] pr = new int[N];
    static boolean[] st = new boolean[N];
    
    //在线性筛的过程中求欧拉函数
    public static void get_euler(int n){
        phi[1] = 1;
        int cnt = 0;
        for(int i = 2; i <= n; i ++){
            if(!st[i]){//在这个if里的都是质数
                pr[cnt ++] = i;
                phi[i] = i - 1;//一个质数与所有小于它的数都互质
            }
            for(int j = 0; pr[j] <= n / i; j ++){
                st[pr[j] * i] = true;
                if(i % pr[j] == 0){
                    phi[i * pr[j]] = pr[j] * phi[i];//由公式推导而来
                    break;
                } 
                phi[i * pr[j]] = (pr[j] - 1) * phi[i];//公式推导
            }
        }
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        get_euler(n);
        long res = 0;
        for(int i :phi){
            res += i;//把每个数的欧拉函数相加
        }
        System.out.print(res);
    }
}

2.快速幂

(1)快速幂

 875. 快速幂 - AcWing题库

import java.io.*;
import java.util.*;

public class Main{
    public static int quick(int a, int k, int p){
        int res = 1;
        while(k != 0){
            if((k & 1) == 1){//k与1,判断k的二进制的最后一位是不是1,如果是的话执行下面的操作
                res = (int)((long) res * a % p);
            }
            k >>= 1;//将k的二进制向右移动一位,以便下一次的判断
            a = (int)((long)a * a % p);//把a的多少次方先算出来,每次循环的a都是在上一次a的基础上变化的
        }
        return res;
    }
    
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        while(n -- > 0){
            String[] str = br.readLine().split(" ");
            int a = Integer.parseInt(str[0]);
            int k = Integer.parseInt(str[1]);
            int p = Integer.parseInt(str[2]);
            System.out.println(quick(a, k, p));
        }
    }
}

(2)快速幂求逆元

 876. 快速幂求逆元 - AcWing题库

涉及到费马定理 b^(p-1) = 1 (mod p),分解得到 b * b^(p - 2) = 1 (mod p)

import java.util.*;

public class Main{
    public static int quick(int a, int k, int p){
        int res = 1;
        while(k != 0){
            if((k & 1) == 1) res = (int)((long)res * a % p);
            k >>= 1;
            a = (int)((long)a * a % p);
        }
        return res;
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while(n -- > 0){
            int a = sc.nextInt();
            int p = sc.nextInt();
            int res = quick(a, p - 2, p);
            //a与p互质才能用费马定理的公式
            if(a % p != 0) System.out.println(res);
            else System.out.println("impossible");
        }
    }
}

3.扩展欧几里得算法

 (1)扩展欧几里得算法

 877. 扩展欧几里得算法 - AcWing题库

 裴蜀定理:对于任意两个正整数a,b,一定存在非零整数x,y,使得ax + by =  a和b的最大公约数。

import java.util.*;
import java.io.*;

public class Main{
    static int[] x = new int[1], y = new int[1];
    public static int exgcd(int a, int b, int[] x, int[] y){
        if(b == 0){
            //如果b等于0,那么gcd(a,b)就等于a,所以ax + 0y = a 则 x = 1,y = 0
            x[0] = 1;
            y[0] = 0;
            return a;
        }else{
            //由欧几里得算法得:gcd(a,b) = gcd(b,a % b)
            //ax + by = gcd(a,b), bx + (a % b)y = gcd(b,a % b)
            //所以 by + (a % b)x = gcd(a,b)  
            //由(a % b ) = a - (a / b) * b
            //得by + (a - (a / b) * b)x = gcd(a,b)
            //故ax + b(y - (a / b) * x) = gcd(a,b)
            int d = exgcd(b, a % b, y, x);
            y[0] -= (a / b) * x[0];
            return d;
        }
    }
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        while(n -- > 0){
            String[] str = br.readLine().split(" ");
            int a = Integer.parseInt(str[0]);
            int b = Integer.parseInt(str[1]);
            exgcd(a, b, x, y);
            System.out.println(x[0] + " " + y[0]);
        }
    }
}

(2)线性同余方程

 878. 线性同余方程 - AcWing题库

 

import java.util.*;

public class Main{
    static int[] x = new int[1], y = new int[1];
    
    public static int gcd(int a, int b, int[] x, int[] y){
        if(b == 0){
            x[0] = 1;
            y[0] = 0;
            return a;
        }
        int d = gcd(b, a % b, y, x);
        y[0] -= (a / b) * x[0];
        return d;
    }
    
    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();
            int m = sc.nextInt();
            int d = gcd(a, m, x, y);
            if(b % d != 0) System.out.println("impossible");
            else System.out.println((long)x[0] * b / d % m);
        }
    }
}

4.中国剩余定理

AcWing 204. 表达整数的奇怪方式 - AcWing

这个太难le,过几天回来补 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值