【蓝桥杯备赛】数论专题

数论知识点汇总

常用函数

swap

交换两个数

public static void swap(int a, int b){
    a=a^b;
    b=a^b;
    a=a^b;
}
public static void swap(int a, int b){
    int t = a;
    a = b;
    b = a;
}

最大公因数gcd

public static int gcd(int m, int n) { // 最大公因数
    if (m % n == 0)
        return n;
    return gcd(n, m % n);
}

public static int gcd(int a, int b) { // 最大公因数
    return b != 0 ? gcd(b, a % b) : a;
}

最小公倍数lcm

两者的关系

xy = gcd * lcm

 public static int lcm(int m, int n) { // 最小公倍数
    return m * n / gcd(m, n);
}

扩展欧几里得算法exgcd

https://www.acwing.com/problem/content/879/
【蓝桥杯备赛】数论专题_第1张图片

原理:
【蓝桥杯备赛】数论专题_第2张图片

static int x,y;
public static int exgcd(int a, int b){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    int d = exgcd(b,a % b);
    int temp = y;
    y = x - a/b * y;
    x = temp;
    return d;
}

同余定理

原理就是利用扩展欧几里得算法来进行求解

https://www.acwing.com/problem/content/880/

ax - my = b
ax + my' = b
求gcd(a,m) = d
如果b % d == 0则有解
解等于 x * (b/d) 
为了保证结果在int范围内要mod m

https://www.acwing.com/problem/content/1301/

当利用exgcd求出了一组解(x0,y0)后,可以用其表示通解
x = x0 + kb
y = y0 - ka
因此求出一个解x后,如果希望x满足x > 0
则可以让x = x0 + kb
即x0对b取正mod
((x0%b) + b ) % b

取整

下取整a/b

上取整(a+b-1)/b

取模

让负数正数都取绝对值的mod

(a%b+b)%b

判断闰年

//满足以下则是闰年
i%4==0&&i%100!=0||i%400==0

质数

试除法判断

// 没优化版本 O(n)
public static boolean is_prime(int n){
    if(n < 2) return false;
    for(int i = 2; i < n; i++){
        if(n % i == 0) return false;
    }
    return true;
}
// 优化版本 O(sqrt(n))
// 原理:如果 d | n (整除)则 n / d | n 因此只需要枚举到sqrt(n)
public static boolean is_prime_2(int n){
    if(n < 2) return false;
    for(int i = 2; i <= n / i; i++){
        if(n % i == 0) return false;
    }
    return true;
}

筛质数

  • 埃氏筛
  • 欧拉筛(更快)
import java.util.*;
public class Main{
    static Scanner sc = new Scanner(System.in);
    static int N = 1000010;
    static int cnt = 0;
    static int[] primes = new int[N];
    static boolean[] st = new boolean[N];
    // 埃氏筛法:对于每个质数,把他的合数筛掉 O(nlognlogn)
    public static void get_primes_ai(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;
                }
            }
        }
    }
    // 欧拉筛
    // 每个数只会被他的最小质因子筛掉
    public static void get_primes_euler(int n){
        for(int i = 2; i <= n; i++){
            if(!st[i]) primes[cnt++] = i;
            for(int j = 0; primes[j] * i <= n; j++){
                st[primes[j] * i] = true;
                if(i % primes[j] == 0) break;
            }

        }
    }
    public static void main(String[] args){
        int n = sc.nextInt();
        get_primes_euler(n);
        System.out.print(cnt);
    }
}

分解质因数

本质也是试除法,遍历[2,sqrt(n)],如果是质数就除

最后如果n > 1要把n加上

//因式分解后求和
public List<Integer> yinshi(int n){
    List<Integer> list = new ArrayList<>();
    for(int i = 2; i <= n / i; i++){
        while(n % i == 0){
            list.add(i);
            n/=i;
        }
    }
    if(n > 1) list.add(n);
    return list;
}


public static void divide(int n){
    for(int i = 2; i <= n / i; i++){
        if(n % i == 0){
            int num = 0;
            while(n % i == 0){
                n /= i;
                num++;
            }
            System.out.println(i + " " + num);
        }
    }
    if(n > 1){
        System.out.println(n + " " + 1);
    }
    System.out.println();
}

约数

约数是指可以整除数x的数

【蓝桥杯备赛】数论专题_第3张图片

每个数都可以拆解为N = P_1^{d1} * P_2^{d2} ... P_k^{dk}

Pi表示质数,di表示质数的个数

约数个数为(d_1+1)(d_2+1)(d_k+1)

约数之和(1+P_1+P_1^2+...+P_1^{d1})(1+...+P_2^{d2})(1+...+P_k^{dk})

组合理论

多重组合理论求方案数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FyL5FfEz-1680095535219)(img/1679484367115-7839053f-46a6-429e-9aea-63868c67a2b8.png)]

高中知识

a1 a2 ak都是一类相同的数,求排列方案,total! / 每一类的阶乘

回文串

判断回文串和求回文串

双指针

public static boolean isHuiWen(String str){
    int i = 0, j = str.length() - 1;
    while (i < j){
        if(str.charAt(i) != str.charAt(j)) return false;
        i++;
        j--;
    }
    return true;
}

利用前四位数求出回文串

int date = i, x = i;
//求回文
for(int j = 0; j < 4 ; j++){
    date = date * 10 + x % 10;
    x /= 10;
}

你可能感兴趣的:(蓝桥杯,java,算法)