08.01_基础数论

基础数论

问题描述

基础数论处理整数的基本性质和关系,包括质数判定、最大公约数、质因数分解等问题。

质数判定

算法思想

  1. 对于一个数n,只需要判断到sqrt(n)
  2. 可以通过筛法预处理优化判定
  3. 适用于单个数的判定
  4. 时间复杂度

代码实现

class Solution {
public:
    bool isPrime(int n) {
        if (n < 2) return false;
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) return false;
        }
        return true;
    }
    
    vector<bool> sieveOfEratosthenes(int n) {
        vector<bool> isPrime(n + 1, true);
        isPrime[0] = isPrime[1] = false;
        
        for (int i = 2; i * i <= n; i++) {
            if (isPrime[i]) {
                for (int j = i * i; j <= n; j += i) {
                    isPrime[j] = false;
                }
            }
        }
        
        return isPrime;
    }
};
class Solution {
    public boolean isPrime(int n) {
        if (n < 2) return false;
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) return false;
        }
        return true;
    }
    
    public boolean[] sieveOfEratosthenes(int n) {
        boolean[] isPrime = new boolean[n + 1];
        Arrays.fill(isPrime, true);
        isPrime[0] = isPrime[1] = false;
        
        for (int i = 2; i * i <= n; i++) {
            if (isPrime[i]) {
                for (int j = i * i; j <= n; j += i) {
                    isPrime[j] = false;
                }
            }
        }
        
        return isPrime;
    }
}
class Solution:
    def isPrime(self, n: int) -> bool:
        if n < 2:
            return False
        for i in range(2, int(n ** 0.5) + 1):
            if n % i == 0:
                return False
        return True
    
    def sieveOfEratosthenes(self, n: int) -> List[bool]:
        is_prime = [True] * (n + 1)
        is_prime[0] = is_prime[1] = False
        
        for i in range(2, int(n ** 0.5) + 1):
            if is_prime[i]:
                for j in range(i * i, n + 1, i):
                    is_prime[j] = False
        
        return is_prime

最大公约数

算法思想

  1. 使用辗转相除法(欧几里得算法)
  2. 基于 gcd(a,b) = gcd(b,a%b)
  3. 可以扩展到求解线性方程
  4. 时间复杂度

代码实现

class Solution {
public:
    int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    
    // 扩展欧几里得算法
    tuple<int, int, int> exgcd(int a, int b) {
        if (b == 0) {
            return {a, 1, 0};
        }
        int d, x, y;
        tie(d, x, y) = exgcd(b, a % b);
        return {d, y, x - (a / b) * y};
    }
};
class Solution {
    public int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    
    // 扩展欧几里得算法
    public int[] exgcd(int a, int b) {
        if (b == 0) {
            return new int[]{a, 1, 0};
        }
        int[] result = exgcd(b, a % b);
        int d = result[0], x = result[1], y = result[2];
        return new int[]{d, y, x - (a / b) * y};
    }
}
class Solution:
    def gcd(self, a: int, b: int) -> int:
        return a if b == 0 else self.gcd(b, a % b)
    
    # 扩展欧几里得算法
    def exgcd(self, a: int, b: int) -> Tuple[int, int, int]:
        if b == 0:
            return a, 1, 0
        d, x, y = self.exgcd(b, a % b)
        return d, y, x - (a // b) * y

时间复杂度分析

算法 时间复杂度 空间复杂度
质数判定
埃氏筛
欧几里得
扩展欧几里得

应用场景

  1. 质数判定
  2. 质因数分解
  3. 最大公约数
  4. 最小公倍数
  5. 线性方程求解

注意事项

  1. 数据范围的考虑
  2. 溢出的处理
  3. 特殊情况的判断
  4. 预处理的时机
  5. 算法的选择

常见变形

  1. 最小公倍数
long long lcm(int a, int b) {
    return (long long)a / gcd(a, b) * b;  // 使用long long防止溢出
}
class Solution {
    public long lcm(int a, int b) {
        return (long)a / gcd(a, b) * b;  // 使用long防止溢出
    }
}
class Solution:
    def lcm(self, a: int, b: int) -> int:
        return a // self.gcd(a, b) * b  # 使用整除防止浮点数
  1. 质因数分解
vector<pair<int, int>> factorize(int n) {
    vector<pair<int, int>> factors;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            int cnt = 0;
            while (n % i == 0) {
                cnt++;
                n /= i;
            }
            factors.emplace_back(i, cnt);
        }
    }
    if (n > 1) {
        factors.emplace_back(n, 1);
    }
    return factors;
}
class Solution {
    public List<int[]> factorize(int n) {
        List<int[]> factors = new ArrayList<>();
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) {
                int cnt = 0;
                while (n % i == 0) {
                    cnt++;
                    n /= i;
                }
                factors.add(new int[]{i, cnt});
            }
        }
        if (n > 1) {
            factors.add(new int[]{n, 1});
        }
        return factors;
    }
}
class Solution:
    def factorize(self, n: int) -> List[Tuple[int, int]]:
        factors = []
        i = 2
        while i * i <= n:
            if n % i == 0:
                cnt = 0
                while n % i == 0:
                    cnt += 1
                    n //= i
                factors.append((i, cnt))
            i += 1
        if n > 1:
            factors.append((n, 1))
        return factors

经典例题

  1. 小红走网格
  2. 小红和小紫的取素因子游戏
  3. 游游的最小公倍数
  4. 小苯的数字权值
  5. 墙壁划线
牛客代码笔记-牛栋 文章被收录于专栏

汗牛充栋,学海无涯。<br/> 内含算法知识点讲解,以及牛客题库精选例题。<br/> 学习算法,从牛栋开始。

全部评论

相关推荐

05-09 12:23
已编辑
华南理工大学 Java
野猪不是猪🐗:给他装的,双九+有实习的能看的上这种厂我直接吃⑨✌们拿它练练面试愣是给他整出幻觉了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务