马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在刷 LeetCode 的过程中,我们常常会碰到各种数学题,这类题目每每无法仅靠暴力法取胜,背后的数学原理才是通关关键。本文将详细整理 LeetCode 常见数学本领,包括理论 + 高质量 C++ 实现。
1. 乘法逆元(Modular Multiplicative Inverse)
应用场景
当你需要在模意义下“除以一个数”时,就要用它的 乘法逆元。
通常用于:
C++ 实现(基于费马小定理,模数必须是质数)
- int modInverse(int a, int mod) {
- // 快速幂实现 a^(mod-2) % mod
- int res = 1;
- a %= mod;
- int b = mod - 2;
- while (b) {
- if (b & 1) res = 1LL * res * a % mod;
- a = 1LL * a * a % mod;
- b >>= 1;
- }
- return res;
- }
复制代码 2. 二分快速幂(Binary Exponentiation)
应用场景
当你需要计算 a^b % mod,但 b 非常大时,用此方法可在 O(log b) 时间内完成。
- int fastPow(int a, int b, int mod) {
- int res = 1;
- a %= mod;
- while (b) {
- if (b & 1) res = 1LL * res * a % mod;
- a = 1LL * a * a % mod;
- b >>= 1;
- }
- return res;
- }
复制代码 3. 高斯鞋带定理(Shoelace Formula)
应用场景
用于计算多边形面积,常见于几何类题目。
- double polygonArea(const vector<pair<int, int>>& points) {
- int n = points.size();
- long long area = 0;
- for (int i = 0; i < n; i++) {
- int x1 = points[i].first, y1 = points[i].second;
- int x2 = points[(i + 1) % n].first, y2 = points[(i + 1) % n].second;
- area += 1LL * (x1 * y2 - x2 * y1);
- }
- return abs(area) / 2.0;
- }
复制代码 4. 欧拉函数(Euler's Totient Function)
应用场景
用于判断一个数 n 小于它且与它互素的整数数量。
- int eulerTotient(int n) {
- int res = n;
- for (int i = 2; i * i <= n; i++) {
- if (n % i == 0) {
- while (n % i == 0) n /= i;
- res -= res / i;
- }
- }
- if (n > 1) res -= res / n;
- return res;
- }
复制代码 5. 前缀和(Prefix Sum)
应用场景
用于快速查询子数组和、区间统计等问题。
- vector<int> prefixSum(const vector<int>& nums) {
- int n = nums.size();
- vector<int> prefix(n + 1);
- for (int i = 0; i < n; ++i) {
- prefix[i + 1] = prefix[i] + nums[i];
- }
- return prefix;
- }
复制代码 6. 组合数(Combination)+ 预处置惩罚
应用场景
在模意义下计算组合数 C(n,k)C(n, k)C(n,k),多个查询时建议预处置惩罚。
- const int MOD = 1e9 + 7;
- const int MAXN = 1e5 + 10;
- int fact[MAXN], invFact[MAXN];
- void initComb() {
- fact[0] = invFact[0] = 1;
- for (int i = 1; i < MAXN; ++i) {
- fact[i] = 1LL * fact[i - 1] * i % MOD;
- }
- invFact[MAXN - 1] = modInverse(fact[MAXN - 1], MOD);
- for (int i = MAXN - 2; i >= 1; --i) {
- invFact[i] = 1LL * invFact[i + 1] * (i + 1) % MOD;
- }
- }
- int comb(int n, int k) {
- if (k < 0 || k > n) return 0;
- return 1LL * fact[n] * invFact[k] % MOD * invFact[n - k] % MOD;
- }
复制代码 7. 同余模定理(Modular Congruence)
应用场景
用于简化模等式,快速判断两个数模相等。
- bool isCongruent(int a, int b, int mod) {
- return (a - b) % mod == 0;
- }
复制代码 8. 约数个数定理(Divisor Count)
应用场景
用于找出一个数的全部正整数因子的数量。
- int countDivisors(int n) {
- int count = 0;
- for (int i = 1; i * i <= n; ++i) {
- if (n % i == 0) {
- count += (i == n / i) ? 1 : 2;
- }
- }
- return count;
- }
复制代码 9. 最大公约数 & 扩展欧几里得(Extended GCD)
应用场景
办理 ax + by = gcd(a, b) 的整数解,用于求解线性同余方程。
- int gcd(int a, int b) {
- return b == 0 ? a : gcd(b, a % b);
- }
- // 扩展欧几里得
- int extendedGCD(int a, int b, int& x, int& y) {
- if (b == 0) {
- x = 1; y = 0;
- return a;
- }
- int d = extendedGCD(b, a % b, y, x);
- y -= a / b * x;
- return d;
- }
复制代码 10. 埃拉托色尼筛法(Sieve of Eratosthenes)
应用场景
快速生成质数列表,适用于质数计数、质因数分解。
- vector<bool> sieve(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;
- }
复制代码 11. 康托睁开(Cantor Expansion)
应用场景
将一个排列映射为整数(排名),常用于状态压缩、唯一标识。
- int cantor(const vector<int>& perm) {
- int n = perm.size();
- int res = 0;
- vector<int> used(n, 0);
- vector<int> fact(n, 1);
- for (int i = 1; i < n; ++i) fact[i] = fact[i - 1] * i;
- for (int i = 0; i < n; ++i) {
- int cnt = 0;
- for (int j = 0; j < perm[i]; ++j)
- if (!used[j]) ++cnt;
- res += cnt * fact[n - i - 1];
- used[perm[i]] = 1;
- }
- return res;
- }
复制代码 12. 线性筛法(Linear Sieve)
应用场景
与埃氏筛差别,线性筛可以在 O(n) 时间内获取质数和最小质因子,适合用于分解质因数等扩展操作。
- const int MAXN = 1e6;
- int minPrime[MAXN]; // 记录每个数的最小质因数
- vector<int> primes;
- void linearSieve(int n) {
- for (int i = 2; i <= n; ++i) {
- if (minPrime[i] == 0) {
- minPrime[i] = i;
- primes.push_back(i);
- }
- for (int p : primes) {
- if (p > minPrime[i] || i * p > n) break;
- minPrime[i * p] = p;
- }
- }
- }
复制代码 13. 乘法原理(Multiplication Principle)
应用场景
用于计数问题,如排列组合构造、密码锁、数字组合问题等。
例如:长度为 n 的数字序列,每位可以从 0~9 中任选,求方案总数。
- int countSequences(int n) {
- return pow(10, n); // 10^n 个组合
- }
复制代码 14. 排列组合递推公式
应用场景
不使用阶乘时快速求组合数(可避免溢出),适合 n 较大时。
- int comb(int n, int k) {
- long long res = 1;
- for (int i = 1; i <= k; ++i) {
- res = res * (n - i + 1) / i;
- }
- return (int)res;
- }
复制代码 15. 数位 DP(Digit Dynamic Programming)
应用场景
用于计数满意特定性质的整数,例如:统计不包含某些数字的数字数量、0-9 出现频率。
- int dfs(int pos, int lead, int tight, vector<int>& digits) {
- // 省略具体实现,仅展示用法
- // 递归考虑每一位的取值可能
- return 0;
- }
- int countValid(int n) {
- vector<int> digits;
- while (n) {
- digits.push_back(n % 10);
- n /= 10;
- }
- reverse(digits.begin(), digits.end());
- return dfs(0, 1, 1, digits);
- }
复制代码 16. 差分数组(Difference Array)
应用场景
适用于频繁修改某一段区间的值,如:区间 +1 操作、区间覆盖等。
- vector<int> getModifiedArray(int length, vector<vector<int>>& updates) {
- vector<int> diff(length + 1, 0);
- for (auto& u : updates) {
- int l = u[0], r = u[1], val = u[2];
- diff[l] += val;
- diff[r + 1] -= val;
- }
- for (int i = 1; i < length; ++i)
- diff[i] += diff[i - 1];
- diff.pop_back(); // 去掉多余项
- return diff;
- }
复制代码 17. 矩阵快速幂(Matrix Fast Power)
应用场景
常用于求斐波那契数列的第 n 项、线性递推式等问题,时间复杂度 O(logN)。
- struct Matrix {
- long long mat[2][2];
- Matrix operator*(const Matrix& other) const {
- Matrix res{};
- for (int i = 0; i < 2; ++i)
- for (int j = 0; j < 2; ++j)
- for (int k = 0; k < 2; ++k)
- res.mat[i][j] += mat[i][k] * other.mat[k][j];
- return res;
- }
- };
- Matrix matrixPow(Matrix a, int n) {
- Matrix res = {{{1, 0}, {0, 1}}}; // 单位矩阵
- while (n) {
- if (n & 1) res = res * a;
- a = a * a;
- n >>= 1;
- }
- return res;
- }
复制代码 18. 状态压缩(Bitmask Optimization)
应用场景
适用于 n 较小(一般 n <= 20)的组合摆列问题,如旅行商问题、集合划分、状态标志
- // 统计所有子集的和
- int subsetSum(vector<int>& nums) {
- int n = nums.size(), total = 0;
- for (int mask = 0; mask < (1 << n); ++mask) {
- int sum = 0;
- for (int i = 0; i < n; ++i)
- if (mask >> i & 1)
- sum += nums[i];
- total += sum;
- }
- return total;
- }
复制代码 19. 中国剩余定理(Chinese Remainder Theorem, CRT)
应用场景
求一组同余方程的最小正整数解:
- // 求解 x ≡ a1 (mod m1), x ≡ a2 (mod m2)
- int CRT(vector<int>& a, vector<int>& m) {
- int n = a.size();
- long long M = 1, res = 0;
- for (int mi : m) M *= mi;
- for (int i = 0; i < n; ++i) {
- long long Mi = M / m[i];
- long long ti = modInverse(Mi % m[i], m[i]);
- res = (res + a[i] * Mi % M * ti % M) % M;
- }
- return (int)(res % M);
- }
复制代码 20. 最小公倍数(LCM)
应用场景
常常用于模拟轮转、最短时间循环、周期重合类题目。
- int lcm(int a, int b) {
- return a / gcd(a, b) * b;
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |