【算法模板】数学基础算法模版

文章目录

  • 数学基础
    • 试除法判定质数
    • 试除法分解质因数
    • 朴素筛法求素数
    • 线性筛法求素数
    • 试除法求所有约数
    • 约数个数和约数之和
    • 欧几里得算法
    • 求欧拉函数
    • 筛法求欧拉函数
    • 快速幂
    • 扩展欧几里得算法
    • 高斯消元解线性方程组
    • 递推法求组合数
    • 通过预处理逆元的方式求组合数
    • Lucas定理
    • 分解质因数法求组合数


数学基础

试除法判定质数

试除法是判断一个数是否为质数的常见方法。它的核心思想是,将该数从2开始,逐个尝试除以小于等于其平方根的整数。如果在这些尝试中有任何一个整数整除这个数,那么这个数就不是质数;否则,这个数就是质数。

算法思路

  1. 如果数字小于2,直接返回False,因为质数从2开始。
  2. 从2开始,尝试除到小于等于该数平方根的每一个整数。
  3. 如果任何一个整数整除该数,则返回False,否则返回True。
bool is_prime(int x) {if (x < 2) return false;for (int i = 2; i <= x / i; i++)if (x % i == 0)return false;return true;
}

模板题 AcWing 866. 试除法判定质数

试除法分解质因数

试除法用于分解一个整数的质因数,并计算其质因数的次数。其思路是从2开始,逐个尝试整除,直到小于等于该数的平方根。

算法思路:

  1. 从2开始,尝试除到小于等于该数平方根的每一个整数。
  2. 如果该整数能够整除目标数,记录这个质因数以及它的出现次数,直到目标数不再可被整除。
  3. 如果经过所有检查后,目标数仍然大于1,那么该数也是质因数。
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;
}

模板题 AcWing 867. 分解质因数

朴素筛法求素数

朴素筛法,又称埃拉托斯特尼筛法,适用于生成范围内所有素数的列表。其原理是从2开始,筛除每个素数的所有倍数。

算法思路:

  1. 创建一个布尔数组,用于标记数是否是素数,初始时全部设为True。
  2. 从2开始,如果该数没有被标记为非素数,则认为它是素数,并标记它的所有倍数为非素数。
  3. 重复以上步骤,直到到达范围上限。
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;}
}

模板题 AcWing 868. 筛质数

线性筛法求素数

线性筛法是对朴素筛法的改进,确保每个合数只被其最小质因子筛选一次。其优点在于复杂度更低,每个合数只被筛选一次。

算法思路:

  1. 创建一个布尔数组,用于标记数是否是素数。
  2. 从2开始,如果该数没有被标记为非素数,则添加到素数列表中。
  3. 对于每个素数,如果当前数乘以素数不超过范围上限,则标记其为非素数。若当前数被素数整除,停止进一步标记。
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;}}
}

模板题 AcWing 868. 筛质数

试除法求所有约数

试除法用于求一个整数的所有约数。其思路是从1开始,逐个尝试到该数的平方根,找出所有的约数。

算法思路:

  1. 从1开始,尝试到小于等于该数平方根的每一个整数。
  2. 如果该整数能够整除目标数,则记录这个整数和相应的商。
  3. 返回所有找到的约数,并按从小到大的顺序排序。
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;
}

模板题 AcWing 869. 试除法求约数

约数个数和约数之和

这两个公式用于计算一个数的所有约数的个数和它们的总和。算法基于该数的质因数分解。

算法思路:

  1. 首先对数进行质因数分解,获得每个质因数和对应的次数。
  2. 约数个数的计算:每个质因子的次数加1,然后所有质因子次数的乘积。
  3. 约数之和的计算:对于每个质因子,求其从0到对应的次数的幂之和,然后将所有质因子幂之和相乘。
// 如果 N = p1^c1 * p2^c2 * ... * pk^ck
// 约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
// 约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)

关于取模

(a + b) % p = (a%p + b%p) %p 
(a - b) % p = (a%p - b%p) %p 
(a * b) % p = (a%p * b%p) %p 

这是一个关于正整数因数分解的公式。在公式中,N是一个正整数,表示为质因数分解形式:N = p1^c1 * p2^c2 * … * pk^ck,其中p1, p2, …, pk是N的所有质因数,c1, c2, …, ck分别是它们的对应指数。

根据你提供的公式:

  • N的约数个数可以通过公式 (c1 + 1) * (c2 + 1) * … * (ck + 1) 来计算,即将每个质因数的指数加1后相乘得到约数个数。
  • N的约数之和可以通过公式 (p1^0 + p1^1 + … + p1^c1) * … * (pk^0 + pk^1 + … + pk^ck) 来计算,即将每个质因数的幂次相加后相乘得到约数之和。

计算正整数N的约数个数

int numDivisors(int N) {int num = 1;for (int i = 2; i <= sqrt(N); i++) {int exp = 0;while (N % i == 0) {exp++;N /= i;}num *= (exp + 1);}if (N > 1) {num *= 2;}return num;
}

计算正整数N的约数之和

int sumOfDivisors(int N) {int sum = 1;for (int i = 2; i <= sqrt(N); i++) {if (N % i == 0) {int current_term = 1;int factor = 1;while (N % i == 0) {factor *= i;current_term += factor;N /= i;}sum *= current_term;}}if (N > 1) {sum *= (1 + N);}return sum;
}

模板题 AcWing 870. 约数个数, AcWing 871. 约数之和

欧几里得算法

欧几里得算法用于求解两个整数的最大公约数。它基于辗转相除的原则,即不断求解两个数的余数,直到余数为零。

算法思路:

  1. 给定两个整数a和b,如果b为零,则最大公约数是a。
  2. 否则,计算a除以b的余数,重新调用算法,用b和余数进行迭代。
  3. 直到余数为零,得到最大公约数。
int gcd(int a, int b) {return b ? gcd(b, a % b) : a;
}

模板题 AcWing 872. 最大公约数

求欧拉函数

欧拉函数(\phi(x))用于计算小于等于x且与x互质的正整数的数量。计算欧拉函数通常需要质因数分解。

算法思路:

  1. 初始化结果为x。
  2. 从2开始,尝试整除目标数。如果能整除,则将结果乘以(1 - 1/p)。
  3. 对每个质因子,重复上述步骤,直到目标数被完全分解。
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;
}

模板题 AcWing 873. 欧拉函数

筛法求欧拉函数

筛法用于快速求解从1到某个范围内的所有欧拉函数。这种方法通过结合线性筛法来提高效率。

算法思路:

  1. 创建一个布尔数组,用于标记数是否是素数,并初始化一个数组存储欧拉函数值。
  2. 从2开始,如果该数没有被标记为非素数,则它是素数,并设置其欧拉函数值。
  3. 对于每个素数,计算其倍数的欧拉函数值,并根据质因子的关系调整欧拉函数值。
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);}}
}

模板题 AcWing 874. 筛法求欧拉函数

快速幂

快速幂算法用于快速计算(a^b \mod p)。其主要思想是通过二进制拆分幂次,以减少计算量。

算法思路:

  1. 初始化结果为1,并设置当前幂次。
  2. 根据k的二进制表示,对每一位进行判断。如果最低位为1,则将当前幂次乘到结果中。
  3. 将幂次平方,并右移二进制表示的最低位。
  4. 重复上述步骤,直到幂次完全被处理。
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;
}

模板题 AcWing 875. 快速幂

扩展欧几里得算法

扩展欧几里得算法除了求解最大公约数,还能求得线性组合方程的整数解。其在求解一些数论和密码学问题时非常有用。

算法思路:

  1. 如果b为零,返回a作为最大公约数,同时设置x为1,y为0。
  2. 否则,递归调用算法,求解b和a % b的最大公约数,并交换x和y的顺序。
  3. 根据线性组合方程,调整x和y,以满足ax + by的关系。

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;
}

模板题 AcWing 877. 扩展欧几里得算法

高斯消元解线性方程组

高斯消元算法用于求解线性方程组。它通过行列变换和消元来简化方程,最终获得解的形式。

算法思路:

  1. 通过行变换,将最大的系数移动到主对角线。
  2. 对于每个列,通过消元使得该列以下所有行的元素为零。
  3. 当完成所有列的操作后,若未完成所有行,则检测是否存在无解的情况。
  4. 对已消元的方程组,进行回代求解。
int gauss() {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; // 有唯一解
}

模板题 AcWing 883. 高斯消元解线性方程组

递推法求组合数

递推法用于计算组合数。它利用递推关系,通过前序计算得出组合数的结果。

算法思路:

  1. 创建一个二维数组,存储组合数的计算结果。
  2. 通过递推关系,计算每一层的组合数。
  3. 遍历递推关系,填充组合数数组,直到计算出所有组合数。
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;

模板题 AcWing 885. 求组合数 I

通过预处理逆元的方式求组合数

该方法使用快速幂计算逆元,以求出组合数的结果。它在模数情况下特别有用。

算法思路:

  1. 通过快速幂计算每个数的阶乘和阶乘的逆元。
  2. 使用组合数公式进行组合数的计算。
  3. 通过逆元的方式,避免直接除法操作。

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;
}

模板题 AcWing 886. 求组合数 II

Lucas定理

Lucas定理用于求组合数,并可应用于大数情况下的组合数计算。

算法思路:

  1. 将组合数按模数分解为若干部分。
  2. 使用递归和分治法计算每一部分的组合数。
  3. 最终将所有部分的组合数乘积,获得组合数的结果。
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;
}

模板题 AcWing 887. 求组合数 III

分解质因数法求组合数

这种方法通过分解质因数的方式,求出组合数的真实值。

算法思路:

  1. 使用线性筛法,计算范围内的所有质数。
  2. 通过计算每个质因子的次数,求得组合数的质因数分解结果。
  3. 使用高精度乘法,将所有质因子按相应次数相乘,获得组合数的真实值。
当我们需要求出组合数的真实值,而非对某个数的余数时,分解质因数的方式比较好用:1. 筛法求出范围内的所有质数2. 通过 C(a, b) = a! / b! / (a - b)! 这个公式求出每个质因子的次数。 n! 中p的次数是 n / p + n / p^2 + n / p^3 + ...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]);

模板题 AcWing 888. 求组合数 IV

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

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

相关文章

微信小程序4~6章总结

目录 第四章 页面组件总结 4.1 组件的定义及属性 4.2 容器视图组件 4.2.1 view 4.2.2 scroll-view 4.2.3 swiper 4.3 基础内容组件 4.3.1 icon ​编辑 4.3.2 text 4.3.3 progress ​编辑 4.4 表单组件 4.4.1 button 4.4.2 radio 4.4.3 checkbox 4.4.4 switch …

C语言--贪吃蛇小游戏

目录 一、Win32API介绍 1.1Win32API 1.2控制台程序 1.3控制台屏幕上的坐标COORD 1.4GetStdHandle 1.5GetConsoleCursorInfo 1.6 CONSOLE_CURSOR_INFO 1.7 SetConsoleCursorInfo 1.8SetConsoleCursorPosition 1.9GetAsyncKeyState 二、贪吃蛇游戏设计与分析 2.1地图 …

手机群控操作软件分析

随着移动互联网的快速发展,智能手机已经成为人们生活中不可或缺的一部分。无论是工作、学习还是娱乐,手机都扮演着重要的角色。然而,随着手机数量的不断增加,对于大量手机的集中管理和操作变得愈发困难。为了解决这一问题,手机群控操作软件应运而生。本文将对手机群控操作…

网站内容下载软件有哪些 网站内容下载软件推荐 网站内容下载软件安全吗 idm是啥软件 idm网络下载免费

一招搞定网页内容下载&#xff0c;并且各大网站通用&#xff01;绕过资源审查&#xff0c;所有网站内容随意下载。解锁速度限制&#xff0c;下载即高速无视网站限速。跳过会员充值&#xff0c;所有VIP资源免费下载。有关网站内容下载软件有哪些&#xff0c;网站内容下载软件推荐…

【leetcode】快慢指针相关题目总结

141. 环形链表 判断链表是否有环&#xff1a;如果链表中存在环&#xff0c;则在链表上不断前进的指针会一直在环里绕圈子&#xff0c;且不能知道链表是否有环。使用快慢指针&#xff0c;当链表中存在环时&#xff0c;两个指针最终会在环中相遇。 /*** Definition for singly-…

代谢组数据分析四:功能分析

Functional Analysis 代谢物通路包含了基因、催化酶或代谢物等上下游关系的先验知识,通过将关心的代谢物比对到通路上,再根据如超级几何分析等数学方法计算受影响的代谢物是否能够影响通路。 代谢物富集分析的目的是为了解析某些差异代谢物是否落在某些pathway上(可简单理…

Ubuntu-22.04电源选项设置

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言说明一、图形设置二、命令行设置1.查看支持的模式2.设置新模式 总结 前言 我们使用Windows都知道电源选项有省电、平衡和高性能模式。其实Ubuntu-22.04也有这个…

【Linux】文件系统

送给大家一句话&#xff1a; 你的任务&#xff0c;就是珍惜你自己的人生&#xff0c;而且还要比之前任何时候更加珍惜。 – 东野圭吾 文件系统 1 前言2 物理磁盘3 磁盘的存储结构4 抽象理解磁盘储存5 引入文件系统 &#xff08;如何管理磁盘文件&#xff09;5.1 了解文件系统5.…

基于 SpringCloud 的在线交易平台乐优商城的设计与实现(六)

目录 第六章 系统测试 6.1 功能性测试 6.1.1 商家后台功能测试 6.1.2 前台功能测试 6.2 非功能性测试 6.3 本章小结 结束语 参考文献 前面内容请移步 基于 SpringCloud 的在线交易平台乐优商城的设计与实现&#xff08;五&#xff09; 相关免费源码资源 乐优商城…

SpringBoot JPA使用

SpringBoot JPA使用 简介 Spring Data JPA 是 Spring 框架提供的一个模块&#xff0c;用于简化与关系型数据库的交互和数据访问。它基于JPA&#xff08;Java Persistence API&#xff09;标准&#xff0c;并提供了一组易于使用的API和工具&#xff0c;帮助开发人员更轻松地进…

深入理解分布式事务① ---->分布式事务基础(四大特性、五大类型、本地事务、MySQL并发事务问题、MySQL事务隔离级别命令设置)详解

目录 深入理解分布式事务① ---->分布式事务基础&#xff08;四大特性、五大类型、本地事务、MySQL并发事务问题、MySQL事务隔离级别命令设置&#xff09;详解事务的基本概念1、什么是事务&#xff1f;2、事务的四大特性2-1&#xff1a;原子性&#xff08;Atomic&#xff09…

(学习日记)2024.04.30:UCOSIII第五十四节:User文件夹函数概览(uCOS-III->Ports文件夹)

之前的章节都是针对某个或某些知识点进行的专项讲解,重点在功能和代码解释。 回到最初开始学μC/OS-III系统时,当时就定下了一个目标,不仅要读懂,还要读透,改造成更适合中国宝宝体质的使用方式。在学完野火的教程后,经过几经思考,最后决定自己锦上添花,再续上几章。 这…

Linux深入学习 - 进程

目录 进程描述符 标识一个进程 进程组织 进程之间的关系 如何组织进程 等待队列 进程资源限制 进程切换 硬件上下文 switch_to宏 创建进程 do_fork 内核进程 撤销有一个进程 do_group_exit do_exit函数 Reference 下面开始讨论一个非常重要的抽象&#xff1a;…

黑烟车智能电子抓拍系统大幅度节约人力物力

黑烟车智能电子抓拍系统大幅度节约人力物力&#xff0c;之前黑烟车监测通过执勤交警人工现场监测会耗费大量人力物力&#xff0c;效率较低&#xff0c;现在通过黑烟车智能电子抓拍系统可以大辅导提升监测效率&#xff0c;遗漏少&#xff0c;效率高&#xff0c;值得大力推广。 黑…

【Python数据库】MongoDB

文章目录 [toc]数据插入数据查询数据更新数据删除 个人主页&#xff1a;丷从心 系列专栏&#xff1a;Python数据库 学习指南&#xff1a;Python学习指南 数据插入 from pymongo import MongoClientdef insert_data():mongo_client MongoClient(hostlocalhost, port27017)co…

红米A2/A2+/POCO C51手机秒解BL+快速获取root权限+解谷歌锁刷机救砖教程

红米A2/A2/POCO C51手机是目前小米公司针对于国外用户的1个独立的品牌&#xff0c;或者和国内的红米手机都非常相似&#xff0c;几款手机由于硬件非常接近&#xff0c;我们这里将其放在一起和大家介绍而从他们的代号中我们可以得知&#xff0c;目前A2/POCO的代号为water&#x…

从零学算法1017

1017. 负二进制转换 给你一个整数 n &#xff0c;以二进制字符串的形式返回该整数的 负二进制&#xff08;base -2&#xff09;表示。 注意&#xff0c;除非字符串就是 “0”&#xff0c;否则返回的字符串中不能含有前导零。 示例 1&#xff1a; 输入&#xff1a;n 2 输出&…

ORAN每个端点和每个C平面消息的限制

O-RU每个端点的处理限制 当O-RU的处理粒度是基于端点的&#xff0c;即&#xff0c;在O-RU中处理C/U平面消息的处理资源被分配给每个端点时&#xff0c;O-RU可以对每个端点施加特定限制&#xff0c;例如&#xff0c;endpoint-section-capacity、endpoint-beam-capacity、endpoi…

ctfshow web78 获取flag

第一种&#xff1a;利用input伪协议 ,获取到flag 第二种&#xff1a;利用flter协议,获取到flag https://21d9e58a-c0fd-47ea-a9c4-d875100f2fdb.challenge.ctf.show/?filephp://filter/readconvert.base64-encode/resourceflag.php 得到的结果PD9waHANCg0KLyoNCiMgLSotIGNvZG…

代码随想录算法训练营第12天:滑动窗口和前缀和

代码随想录算法训练营第12天&#xff1a;滑动窗口和前缀和 这里我参考了西法的博客&#xff0c; 467. 环绕字符串中唯一的子字符串(中等)795. 区间子数组个数(中等)904. 水果成篮(中等)992. K 个不同整数的子数组&#xff08;困难&#xff09;1109. 航班预订统计(中等) 前四…