约数、质数、快速幂-实现模板

约数、质数、快速幂

此处不做讲解证明;可以当个工具包,开箱即用

注意点:此处方法实现的类型(intlong),虽适用于大部分情况,但在实际使用中,还需考虑一下数据范围

给大家一个简单参考(Java

  • int − 2 31 ∼ 2 31 − 1 -2^{31} \sim 2^{31} - 1 2312311约为 1 0 9 10^9 109级别
  • long − 2 63 ∼ 2 63 − 1 -2^{63} \sim 2^{63} - 1 2632631约为 1 0 18 10^{18} 1018级别

约数

最大公约数(gcd)

static int gcd(int a, int b) {
    return b != 0 ? gcd(b, a % b): a;
}
输入:
a = 36, b = 24

输出:
12

最小公倍数(lcm)

static int lcm(int a, int b) {
    return a * b / gcd(a, b);
}
输入:
a = 36, b = 24

输出:
72

分解约数

试除法

  • d ≥ N d \ge \sqrt N dN N N N的约数,则 N / d ≤ N N / d \le \sqrt N N/dN 也是 N N N​的约数
  • 因此,我们只需扫描 d = 1 ∼ N d = 1 \sim \sqrt N d=1N ;若能整除,则 N / d N / d N/d也是 N N N的约数

时间复杂度: O ( x ) O(\sqrt x) O(x )

static void divide(int x) {
    for (int i = 1; i <= x / i; i ++) {
        if (x % i == 0) {
            System.out.println(i);

            if (x / i != i) {
                System.out.println(x / i);
            }
        }
    }
}
输入:
x = 100

输出:
1
100
2
50
4
25
5
20
10

质数

质数判断

时间复杂度: O ( x ) O(\sqrt x) O(x )

static boolean isPrime(int x) {
    if (x < 2) {
        return false;
    }

    for (int i = 2; i <= x / i; i ++) {
        if (x % i == 0) {
            return false;
        }
    }
    return true;
}
输入:
x = 23
x = 4

输出:
true
false

筛法求质数

  • primes存储的是小于等于 n n n的所有质数,需要注意的是,此处primes是达不到代码中N这个级别
    • 对于一个足够大的整数 N N N,不超过 N N N的质数大约有 N / ln ⁡ N N / \ln{N} N/lnN

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

static int N = 110;
static int cnt = 0;
static int[] primes = new int[N]; // 此处primes范围是到不了N的,只是开这么多
static boolean[] st = new boolean[N];

// 线性筛法
static void get_primes(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) {
    get_primes(100);

    for (int i = 0; i < cnt; i ++) {
        System.out.print(primes[i] + " ");
    }
}
输入:
n = 100

输出:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 

质数分解

根据算术基本定理,任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作:
N = p 1 c 1 p 2 c 2 ⋯ p m c m N = p_1^{c_1}p_2^{c_2}\cdots p_m^{c_m} N=p1c1p2c2pmcm
其中, c i c_i ci都是正整数, p i p_i pi都是质数,且满足 p 1 < p 2 < ⋯ < p m p_1\lt p_2 \lt \cdots \lt p_m p1<p2<<pm

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

static void divide_primes(int n) {
    for (int i = 2; i <= n / i; i ++) {
        if (n % i == 0) {
            int c_i = 0;

            while (n % i == 0) {
                n /= i;
                c_i ++;
            }

            if (c_i > 0) {
                int p_i = i;
                System.out.printf("p = %d, c = %d\n", p_i, c_i);
            }
        }
    }
    if (n > 1) {
        System.out.printf("p = %d, c = 1\n", n);
    }
}
输入:
n = 1044

输出:
p = 2, c = 2
p = 3, c = 2
p = 29, c = 1

快速幂

  • 从位运算的角度进行考虑

  • a = 2 , b = 10 = 101 0 2 a = 2, b = 10 = 1010_2 a=2,b=10=10102,求 a b a^ b ab

  • a b = 2 2 × 2 8 = 4 × 256 = 1024 a^b = 2^2 \times 2^8 = 4 \times 256 = 1024 ab=22×28=4×256=1024

  • 用到快速幂的题目一般还会有一个取余的要求,用不到的话将函数最后一个参数去掉即可

  • 函数输出: a b m o d    M O D a^b \mod{MOD} abmodMOD

时间复杂度: O ( log ⁡ b ) O(\log{b}) O(logb)

static long qmi(long a, long b, long MOD) {
    long res = 1;

    while (b > 0) {
        if ((b & 1) == 1) {
            res = res * a % MOD;
        }
        a = a * a % MOD;
        b >>= 1;
    }

    return res;
}
输入:
a = 2L, b = 100L, MOD = (long) (1e9 + 7)

输出:
976371285
  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值