0x04 数学知识

news/2025/4/3 1:44:50/文章来源:https://www.cnblogs.com/violet1359/p/18804739

数学知识

数论

质数

试除法判定质数

\(O(\sqrt n)\)

bool is_prime(int x)
{if (x < 2) return false;for (int i = 2; i <= x / i; i ++ )//sqrt(x)较慢,i*i存在溢出风险if (x % i == 0)return false;return true;
}

试除法分解质因数

\(O(\log n) \sim O(\sqrt n)\)

\(n\) 中最多只包含一个大于\(\sqrt n\) 的质因子

void divide(int x)
{for (int i = 2; i <= x / i; i ++ )if (x % i == 0){int s = 0;while (x % i == 0) x /= i, s ++ ;cout << i << ' ' << s << endl;}if (x > 1) cout << x << ' ' << 1 << endl;cout << endl;
}

埃氏筛求质数

\(O(n \log (\log n))\)

int primes[N], cnt;//primes[]存储所有素数
bool st[N];//st[x]存储x是否被筛掉
void get_primes(int n)
{for (int i = 2; i <= n; i ++ ){if (st[i]) continue;primes[cnt ++ ] = i;for (int j = i + i; j <= n; j += i)st[j] = true;}
}

线性筛求质数

\(O(n)\)

每个数只被它最小的质因数筛去

int primes[N], cnt;     // primes[]存储所有素数
bool st[N];         // st[x]存储x是否被筛掉
void get_primes(int n)
{for (int i = 2; i <= n; i ++ ){if (!st[i]) primes[cnt ++ ] = i;for (int j = 0; primes[j] <= n / i; j ++ ){st[primes[j] * i] = true;if (i % primes[j] == 0) break;}}
}

约数

试除法求约数

vector<int> get_divisors(int x)
{vector<int> res;for (int i = 1; i <= x / i; i ++ )if (x % i == 0){res.push_back(i);if (i != x / i) res.push_back(x / i);}sort(res.begin(), res.end());return res;
}

约数个数与约数之和

如果 \(N = p_1^{c_1} \times p_2^{c_2} \dots p_k^{c_k}\)
约数个数:\((c_1 + 1) \times (c_2 + 1) ... (c_k + 1)\)
约数之和:\((p_1^0 + p_1^1 + ... + p_1^{c_1}) \times ... \times (p_k^0 + p_k^1 + ... + p_k^{c_k})\)

欧几里得算法

\((a,b)=(b,a\bmod b)\)

int gcd(int a, int b)
{return b ? gcd(b, a % b) : a;
}

欧拉函数

欧拉函数 \(\varphi (n) : 1\sim n\) 中和 \(n\) 互质的个数

欧拉定理:\(gcd(a,m)=1\) ,则 \(a^{\varphi (m)}\equiv 1\pmod{m}\)

费马小定理:\(p\) 为素数,\(gcd(a,p)=1\),则 \(a^{p-1}\equiv 1\pmod{p}\)

求欧拉函数

\(O(\sqrt{n})\)

\(n=p_1^{\alpha_1}\cdot p_2^{\alpha_2} \cdots p_k^{\alpha_k}\)

  1. \(1\sim n\) 中去掉 \(p_1,p_2,\ldots p_k\) 的所有倍数
  2. 加上所有 \(p_i \cdot p_j\) 的倍数
  3. 减去所有 \(p_i \cdot p_j \cdot p_k\) 的倍数
  4. \(\cdots\cdots\)(容斥原理)

\[\begin{aligned} N & -\frac{N}{p_1}-\frac{N}{p_2} \cdots -\frac{N}{p_k} \\ & +\frac{N}{p_1 \cdot p_2}+\frac{N}{p_1 \cdot p_3}+ \cdots \\ & -\frac{N}{p_1 \cdot p_2 \cdot p_3}-\frac{N}{p_1 \cdot p_2 \cdot p_4}-\cdots \\ & +\frac{N}{p_1 \cdot p_2 \cdot p_3 \cdot p_4} \cdots\cdots \\ = & N(1-\frac{1}{p_1})(1-\frac{1}{p_2}) \cdots (1-\frac{1}{p_k}) \\ \end{aligned}\]

int phi(int x)
{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);return res;
}

筛法求欧拉函数

int primes[N], cnt;     // primes[]存储所有素数
int euler[N];           // 存储每个数的欧拉函数
bool st[N];         // st[x]存储x是否被筛掉
void get_eulers(int n)
{euler[1] = 1;for (int i = 2; i <= n; i ++ ){if (!st[i]){primes[cnt ++ ] = i;euler[i] = i - 1;}for (int j = 0; primes[j] <= n / i; j ++ ){int t = primes[j] * i;st[t] = true;if (i % primes[j] == 0){euler[t] = euler[i] * primes[j];break;}euler[t] = euler[i] * (primes[j] - 1);}}
}

快速幂

\(m^k \pmod{p}\),时间复杂度 \(O(\log k)\)

int qmi(int m, int k, int p)
{int res = 1 % p, t = m;while (k){if (k&1) res = res * t % p;t = t * t % p;k >>= 1;}return res;
}

乘法逆元:\(b,m\) 互质,并且对于任意整数 \(a\) 如果满足 \(b|a\) ,则存在一个整数 \(x\) ,使得 \(\frac{a}{b}\equiv a \times x\pmod{m}\) ,则称 \(x\)\(b\) 的模 \(m\) 乘法逆元,记为 \(b^{-1}\pmod{m}\)

\(b\) 存在乘法逆元的充要条件是 \(b\) 与模数 \(m\) 互质,当模数 \(m\) 为质数时,\(b^{m-2}\) 即为 \(b\) 的乘法逆元

扩展欧几里得算法

裴蜀定理:对于任意两个整数 \(a\)\(b\),存在整数 \(x\)\(y\),使得\(ax+by=gcd⁡(a,b)\)

// 求x, y,使得ax + by = gcd(a, b)
int exgcd(int a, int b, int &x, int &y)
{if (!b){x = 1; y = 0;return a;}int d = exgcd(b, a % b, y, x);y -= (a/b) * x;return d;
}

高斯消元

\(O(n^3)\)

步骤:

  1. 构造增广矩阵
  2. 前向消元,使矩阵变成上三角矩阵
  3. 回代求解
int gauss()// a[N][N]是增广矩阵
{int c, r;for (c = 0, r = 0; c < n; c ++ ){int t = r;for (int i = r; i < n; i ++ )//找到绝对值最大的行if (fabs(a[i][c]) > fabs(a[t][c]))t = i;if (fabs(a[t][c]) < eps) continue;for (int i = c; i <= n; i ++ ) swap(a[t][i], a[r][i]);//将绝对值最大的行换到最顶端for (int i = n; i >= c; i -- ) a[r][i] /= a[r][c];//将当前行的首位变成1for (int i = r + 1; i < n; i ++ )//用当前行将下面所有的列消成0if (fabs(a[i][c]) > eps)for (int j = n; j >= c; j -- )a[i][j] -= a[r][j] * a[i][c];r ++ ;}if (r < n){for (int i = r; i < n; i ++ )if (fabs(a[i][n]) > eps)return 2; // 无解return 1; // 有无穷多组解}//回代求解for (int i = n - 1; i >= 0; i -- )for (int j = i + 1; j < n; j ++ )a[i][n] -= a[i][j] * a[j][n];return 0; // 有唯一解
}

组合数

递推法求组合数

\(C^b_a=C_{a-1}^b+C_{a-1}^{b-1}\)

// c[a][b] 表示从a个苹果中选b个的方案数
for (int i = 0; i < N; i ++ )for (int j = 0; j <= i; j ++ )if (!j) c[i][j] = 1;else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;

预处理逆元求组合数

//首先预处理出所有阶乘取模的余数fact[N],以及所有阶乘取模的逆元infact[N]
//如果取模的数是质数,可以用费马小定理求逆元
int qmi(int a, int k, int p)//快速幂模板
{int res = 1;while (k){if (k & 1) res = (LL)res * a % p;a = (LL)a * a % p;k >>= 1;}return res;
}
// 预处理阶乘的余数和阶乘逆元的余数
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i ++ )
{fact[i] = (LL)fact[i - 1] * i % mod;infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
}

\(Lucas\) 定理

\(p\) 是质数,则对于任意整数 \(1\leqslant m \leqslant n\),有:

\[C^n_m=C^{n\%p}_{m\%p}\times C^{n/p}_{m/p}\mod p \]

int qmi(int a, int k, int p)  // 快速幂模板
{int res = 1 % p;while (k){if (k & 1) res = (LL)res * a % p;a = (LL)a * a % p;k >>= 1;}return res;
}
int C(int a, int b, int p)  // 通过定理求组合数C(a, b)
{if (a < b) return 0;LL x = 1, y = 1;  // x是分子,y是分母for (int i = a, j = 1; j <= b; i --, j ++ ){x = (LL)x * i % p;y = (LL) y * j % p;}return x * (LL)qmi(y, p - 2, p) % p;
}
int lucas(LL a, LL b, int p)
{if (a < p && b < p) return C(a, b, p);return (LL)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}

分解质因数法求组合数

需要求出组合数的真实值,而非对某个数的余数时,适合用分解质因数的方式:

  1. 筛法求出范围内的所有质数
  2. 通过 \(\mathrm{C}^a_b=\cfrac{a!}{b!(a-b)!}\) 求出每个质因子的次数,\(n!\)\(p\) 的次数是\(\cfrac{n}{p}+\cfrac{n}{p^2}+\cfrac{n}{p^3}+\cdots\)
  3. 用高精乘相乘所有质因子
int primes[N], cnt;     // 存储所有质数
int sum[N];     // 存储每个质数的次数
bool st[N];     // 存储每个数是否已被筛掉
void get_primes(int n)      // 线性筛法求素数
{for (int i = 2; i <= n; i ++ ){if (!st[i]) primes[cnt ++ ] = i;for (int j = 0; primes[j] <= n / i; j ++ ){st[primes[j] * i] = true;if (i % primes[j] == 0) break;}}
}
int get(int n, int p)       // 求 n!中的次数
{int res = 0;while (n){res += n / p;n /= p;}return res;
}
vector<int> mul(vector<int> a, int b)       // 高精度乘低精度模板
{vector<int> c;int t = 0;for (int i = 0; i < a.size(); i ++ ){t += a[i] * b;c.push_back(t % 10);t /= 10;}while (t){c.push_back(t % 10);t /= 10;}return c;
}
get_primes(a);  // 预处理范围内的所有质数
for (int i = 0; i < cnt; i ++ )     // 求每个质因数的次数
{int p = primes[i];sum[i] = get(a, p) - get(b, p) - get(a - b, p);
}
vector<int> res;
res.push_back(1);
for (int i = 0; i < cnt; i ++ )     // 用高精度乘法将所有质因子相乘for (int j = 0; j < sum[i]; j ++ )res = mul(res, primes[i]);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/909636.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[T.2] 团队项目:选题和需求分析

Study The Spire :卡牌肉鸽关于这款游戏​ Study The Spire 是一款富有创意的 Rougelike 卡牌游戏,将随机与卡牌构筑要素融入游戏,选择不同卡牌来构筑独特卡组来战胜敌人,精心规划你的路线,获得丰富的游戏体验,在游戏过程中你也会逐渐提升自己的专业领域知识,休闲的同时…

高性能计算-GPU并行扫描

1. 扫描概念对数组arr[N]扫描就是得到数组prefix[N],每个元素是之前arr元素的求和. 开扫描定义:prefix1[N] = { arr[0], arr[0]+arr[1], ..., arr[0]+arr[1]+arr[N-1] } 闭扫描定义: prefix2[N] = { 0, arr[0], arr[0]+arr[1], ..., arr[0]+arr[1]+arr[N-12}2. Hillis steele …

硬盘损坏盘片划伤还能恢复数据资料吗?专业数据恢复公司怎么修复

这是一块台式机电脑里的希捷4T机械硬盘,型号是ST4000DM004,是北京某单位客户寄过来的,描述说是突然损坏不识别,出现了吱吱的异响声,先在北京当地找了一家数据恢复公司做了开盘维修处理,说是盘片有损伤,难度很大,在客户前后多次支付备件服务费后,也仅仅做出了100G左右的…

B+树是如何进行查询的?

千里之行,始于足下。 —— 老子因为一个数据页中的记录是有限的,且主键值是有序的,所以通过对所有记录进行分组,然后将组号(槽号)存储到页目录,使其起到索引作用,通过二分查找的方法快速检索到记录在哪个分组,来降低检索的时间复杂度。 但是,当我们需要存储大量的记录…

使用RAGFlow和Docker部署本地知识库

随着DeepSeek的火热,大模型对与广大开发者越来越触手可及。本文介绍了使用 DeepSeek R1 模型来构建本地知识库。Ollama 管理本地模型首先要了解大模型的管理工具 Ollama:安装 OllamaOllama 官网   点击下载安装 Ollama 客户端;安装成功后打开,在终端中输入以下命令来检查是…

CherryStudio使用

一、概述 CherryStudio 是一款集多模型对话、知识库管理、AI 绘画、翻译等功能于一体的全能 AI 助手平台。 CherryStudio 高度自定义的设计、强大的扩展能力和友好的用户体验,使其成为专业用户和 AI 爱好者的理想选择。无论是零基础用户还是开发者,都能在 CherryStudio 中找到…

app测试——adb基本命令

ADB常用的指令:查看当前连接设备 : adb devices进入到shell : adb shell查看日志 : adb logcat ctrl+c退出安装apk文件 : adb install xxx.apk 安装安卓版本后缀apkk包测试包路径:E:\dcs\two\app\baiduyuedu_5520.apk卸载APP : adb uninstall +包名案例:adb uninstall…

移动端动态化建设的演进与实践:从技术革新到生态繁荣

移动端动态化建设已从技术优化演变为企业战略的核心组成部分。尤其在业务迭代加速、生态竞争加剧的背景下,小程序容器技术以其高效、灵活、合规的特性,成为动态化演进的重要方向。未来,随着5G、AI等技术的普及,动态化将进一步推动应用开发范式的变革,为智能终端生态的繁荣…

快节奏业务增长,还是得App混合开发

在用户需求瞬息万变、全球化竞争加剧的背景下,混合开发已从“成本妥协方案”进化为“战略效率工具”。通过跨端框架与小程序的生态协同,企业不仅能实现业务的快速迭代与全球扩张,更能在技术降本与用户体验间找到最佳平衡点。正如某金融科技公司CEO所言:“混合开发不是选择题…

Actor移动

移动玩家需要先修改控制器,再把控制器的数据给到组件旋转非玩家:set actor world rotation 面朝玩家:find look at rotation + rinterp to玩家:首先修改控制器 get control rotation -> set world rotation移动玩家起手式:获取玩家控制器 add input vector向前:get co…

操作系统纷纷闭源,技术创新如何“弯道超车”?

在操作系统闭源化与多平台流量分散的双重挑战下,小程序容器技术凭借其轻量化、跨平台和容器化技术优势,成为企业降本增效的核心解决方案。未来,随着AI技术的深度赋能与行业协作的加强,小程序有望进一步打破系统边界,推动全球应用生态向开放、智能、高效的方向演进。近年来…

GSoC谷歌编程之夏2025招募中,Apache DolphinScheduler需要你的提案!

GSoC谷歌编程之夏活动火热进行中!今年,Apache DolphinScheduler项目也依然参与其中,设立了有趣且有挑战性的项目任务,与通用OIDC认证有关。欢迎有才华的你们来挑战! GSoC的起源与目的 GSoC 即 Google Summer of Code(谷歌编程之夏),是谷歌公司发起的一项全球性活动,旨…