取模

取模符号:\(x \bmod y\),表示 \(x\) 除以 \(y\) 得到的余数。

例如,

\[5 \bmod 3 = 2\\
7 \bmod 4 = 3\\
3 \bmod 3 = 0\\
\]

设 \(x\) 为被除数,\(y\) 为除数,\(z\) 为余数,则 \(x = k \cdot y + z, k = \lfloor \dfrac{x}{y} \rfloor\)。

模运算

\[\left (a + b \right ) \bmod c = \left (a \bmod c + b \bmod c \right ) \bmod c\\
\left (a - b \right ) \bmod c = \left (a \bmod c - b \bmod c \right ) \bmod c\\
\left (a \cdot b \right ) \bmod c = \left [\left (a \bmod c \right ) \cdot \left (b \bmod c \right ) \right ] \bmod c\\
\]

读入两个数 \(n, p\),现在求 \((n!) \bmod p\) 是多少?\((2 < p \le 10^9, 1 \le n \le 1000)\)

\(\left ( n! \right ) \bmod p = \left [ \left ( n - 1 \right )! \bmod p \times n \bmod p \right] \bmod p\)

#include <iostream>
using namespace std; int n, p; int main() {
cin >> n >> p;
int ans = 1;
for (int i = 1; i <= n; ++ i) {
ans = 1ll * ans * i % p;
}
cout << ans << endl;
return 0;
}

BSGS 算法

名称有很多,什么北上广深啊,等等,学名叫 baby-step giant-step,即大步小布算法。

我们由一个问题引入

给定三个数 \(a, b, p\),\(p\) 是质数,解方程 \(a^x \bmod p = b\)。\((a, b, p \le 10^9)\)

暴力的做法

int solve(int a, int b, int p) {
// O(p)
int v = 1;
for (int x = 0; x <= p - 2; ++ x) {
if (v == b) return x;
v = 1ll * v * a % p;
}
return -1;
}

由 \(a^{p - 1} \bmod p = 1\) 可知,余数会在 \(1\) 处循环。

\[a^{p - 1 + k} \bmod p\\
\begin{aligned}
&= a^{p - 1} \cdot a^k \bmod p\\
&= a^k \bmod p
\end{aligned}
\]

对于该方程,要枚举 \(p - 1\) 个数,那我们将这 \(p - 1\) 个数分组,\(s\) 为每组的大小。

\[a_0 \quad a_1 \quad a_2 \cdots \quad a^{s - 1}\\
\Downarrow (\cdot a^s) \Uparrow (\div a^s)\\
a^s \quad a^{s + 1} \quad a^{s + 2} \cdots a^{2s - 1}\\
a^2s \quad a^{2s + 1} \quad a^{2s + 2} \cdots a^{3s - 1}\\
\]

若第 \(2\) 组数中出现了 \(b\),那么在第 \(1\) 组中,一定出现了 \(b \cdot a^{-s}\)。

#include <set>
using namespace std; int solve(int a, int b, int p) {
int s = sqrt(p);
int v = 1;
set<int> se;
for (int i = 0; i < s; ++ i) {
se.insert(v);
v = 1ll * v * a % p;
}
// O(p / s)
for (int i = 0; i * s <= p; ++ i) { // 看答案是否在第 i 行里面
// 要看 b * a (-is) 是否在第 0 行出现
int c = 1ll * b * qpow(qpow(a, i * s, p), p - 2, p) % p;
if (se.count(c) != 0) {
int v = qpow(a, i * s, p); // 第 i 行的第一个数
for (int j = i * s; ; ++ j) { // O(s)
if (v == b) return j;
v = 1ll * v * a % p;
}
}
}
return -1;
}

复杂度为:\(O(\dfrac{p}{s} + s) = O(\max(\dfrac{p}{s}, s))\)

若取 \(s = \sqrt{p}\),则为 \(O_{\sqrt{p}}\)。

「学习笔记」模运算与 BSGS 算法的更多相关文章

  1. 「学习笔记」FFT 之优化——NTT

    目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...

  2. 「学习笔记」FFT 快速傅里叶变换

    目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...

  3. 「学习笔记」字符串基础:Hash,KMP与Trie

    「学习笔记」字符串基础:Hash,KMP与Trie 点击查看目录 目录 「学习笔记」字符串基础:Hash,KMP与Trie Hash 算法 代码 KMP 算法 前置知识:\(\text{Border} ...

  4. 「学习笔记」Min25筛

    「学习笔记」Min25筛 前言 周指导今天模拟赛五分钟秒第一题,十分钟说第二题是 \(\text{Min25}​\) 筛板子题,要不是第三题出题人数据范围给错了,周指导十五分钟就 \(\text{AK ...

  5. 「学习笔记」Treap

    「学习笔记」Treap 前言 什么是 Treap ? 二叉搜索树 (Binary Search Tree/Binary Sort Tree/BST) 基础定义 查找元素 插入元素 删除元素 查找后继 ...

  6. 「学习笔记」平衡树基础:Splay 和 Treap

    「学习笔记」平衡树基础:Splay 和 Treap 点击查看目录 目录 「学习笔记」平衡树基础:Splay 和 Treap 知识点 平衡树概述 Splay 旋转操作 Splay 操作 插入 \(x\) ...

  7. 「学习笔记」wqs二分/dp凸优化

    [学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...

  8. 「学习笔记」递推 & 递归

    引入 假设我们想计算 \(f(x) = x!\).除了简单的 for 循环,我们也可以使用递归. 递归是什么意思呢?我们可以把 \(f(x)\) 用 \(f(x - 1)\) 表示,即 \(f(x) ...

  9. 「学习笔记」ST表

    问题引入 先让我们看一个简单的问题,有N个元素,Q次操作,每次操作需要求出一段区间内的最大/小值. 这就是著名的RMQ问题. RMQ问题的解法有很多,如线段树.单调队列(某些情况下).ST表等.这里主 ...

  10. 「学习笔记」Fast Fourier Transform

    前言 快速傅里叶变换(\(\text{Fast Fourier Transform,FFT}\) )是一种能在\(O(n \log n)\)的时间内完成多项式乘法的算法,在\(OI\)中的应用很多,是 ...

随机推荐

  1. Java数据类型、标识符

    目录 JavaSE 标识符 数据类型 基本数据类型 引用数据类型 转义字符 JavaSE 标识符 定义 Java中用于定义名称的都是标识符.例:包名,类名,变量名,方法名等. 组成 由数字.字母._. ...

  2. ICMP隐蔽隧道攻击分析与检测(三)

    • ICMP隧道攻击工具特征分析 一.原理 由于ICMP报文自身可以携带数据,而且ICMP报文是由系统内核处理的,不占用任何端口,因此具有很高的隐蔽性. 通过改变操作系统默认填充的Data,替换成自己 ...

  3. Python的函数和方法如何区分呢?

    结论>>>:无论是函数还是方法都用def关键字来定义 方法:只要是自动传值都是方法.由谁来调用.会把自身传入 函数:有几个值就传几个值否则会报错 目录 一.详细介绍函数和方法 二.用 ...

  4. kubectl管理多个集群配置

    需求描述:在一台机器上通过kubectl管理多个Kubernetes集群. 操作过程:将各集群的kubectl config文件中的证书内容转换,通过命令创建config文件:通过上下文切换使用不同集 ...

  5. java idea配置流程

    这篇文章主要介绍了IntelliJ IDEA2021.1 配置大全(超详细教程),需要的朋友可以参考下 一.IDEA下载 idea.jdk.tomcat.maven下载地址请参考上一篇博客:https ...

  6. .NET敏捷开发框架-RDIFramework.NET V5.1发布(跨平台)

    RDIFramework.NET,基于全新.NET Framework与.NET Core的快速信息化系统敏捷开发.整合框架,给用户和开发者最佳的.Net框架部署方案.为企业快速构建跨平台.企业级的应 ...

  7. 笔记十:线程间的通信(pthread_exit()和pthread_join())

    linux高级编程之线程间的通信(pthread_exit()和pthread_join()) 1.线程终止      如果进程中的任一线程调用了exit._Exit或者_exit,那么整个进程就会终 ...

  8. 省选联考2021vp记

    卡牌游戏 考虑到将 \(a\) 和 \(b\) 放在一起排序,最后朝上的数字必然在左端点为最小值,右端点为最大值的区间中.这个区间中至少有 \(n-m\) 个是原来的 \(a\),且对于每张卡牌必然要 ...

  9. ATL创建的ActiveX实现JS回调

    最近公司的产品需要使用ActiveX文件上传.讨论了基本所有的技术,最后还是决定C++搞个ActiveX...但上传的回调费了半天劲,才搞定.代码如下 STDMETHODIMP CFileSelect ...

  10. ADG无法切换:报错 ORA-16467

    现象: ADG无法切换:验证时就报错 ORA-16467 记录问题,顺便展现一次troubleshooting的心路历程. 具体查询: 在主库操作, @primary 切换验证: alter data ...