「学习笔记」模运算与 BSGS 算法
取模
取模符号:\(x \bmod y\),表示 \(x\) 除以 \(y\) 得到的余数。
例如,
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 \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\) 处循环。
\begin{aligned}
&= a^{p - 1} \cdot a^k \bmod p\\
&= a^k \bmod p
\end{aligned}
\]
对于该方程,要枚举 \(p - 1\) 个数,那我们将这 \(p - 1\) 个数分组,\(s\) 为每组的大小。
\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 算法的更多相关文章
- 「学习笔记」FFT 之优化——NTT
目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...
- 「学习笔记」FFT 快速傅里叶变换
目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...
- 「学习笔记」字符串基础:Hash,KMP与Trie
「学习笔记」字符串基础:Hash,KMP与Trie 点击查看目录 目录 「学习笔记」字符串基础:Hash,KMP与Trie Hash 算法 代码 KMP 算法 前置知识:\(\text{Border} ...
- 「学习笔记」Min25筛
「学习笔记」Min25筛 前言 周指导今天模拟赛五分钟秒第一题,十分钟说第二题是 \(\text{Min25}\) 筛板子题,要不是第三题出题人数据范围给错了,周指导十五分钟就 \(\text{AK ...
- 「学习笔记」Treap
「学习笔记」Treap 前言 什么是 Treap ? 二叉搜索树 (Binary Search Tree/Binary Sort Tree/BST) 基础定义 查找元素 插入元素 删除元素 查找后继 ...
- 「学习笔记」平衡树基础:Splay 和 Treap
「学习笔记」平衡树基础:Splay 和 Treap 点击查看目录 目录 「学习笔记」平衡树基础:Splay 和 Treap 知识点 平衡树概述 Splay 旋转操作 Splay 操作 插入 \(x\) ...
- 「学习笔记」wqs二分/dp凸优化
[学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...
- 「学习笔记」递推 & 递归
引入 假设我们想计算 \(f(x) = x!\).除了简单的 for 循环,我们也可以使用递归. 递归是什么意思呢?我们可以把 \(f(x)\) 用 \(f(x - 1)\) 表示,即 \(f(x) ...
- 「学习笔记」ST表
问题引入 先让我们看一个简单的问题,有N个元素,Q次操作,每次操作需要求出一段区间内的最大/小值. 这就是著名的RMQ问题. RMQ问题的解法有很多,如线段树.单调队列(某些情况下).ST表等.这里主 ...
- 「学习笔记」Fast Fourier Transform
前言 快速傅里叶变换(\(\text{Fast Fourier Transform,FFT}\) )是一种能在\(O(n \log n)\)的时间内完成多项式乘法的算法,在\(OI\)中的应用很多,是 ...
随机推荐
- java多线程--6 死锁问题 锁Lock
java多线程--6 死锁问题 锁Lock 死锁问题 多个线程互相抱着对方需要的资源,然后形成僵持 死锁状态 package com.ssl.demo05; public class DeadLock ...
- Java面试——搜索
更多内容,前往 IT-BLOG 一.Elasticsearch了解多少 ElasticSearch 是一个基于 Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTfu ...
- Java面试——缓存
一.什么是缓存 [1]缓存就是数据交换的缓冲区(称作:Cache),当某一硬件要读取数据时,会首先从缓存中查询数据,有则直接执行,不存在时从磁盘中获取.由于缓存的数据比磁盘快的多,所以缓存的作用就是帮 ...
- 论文解读(CosFace)《CosFace: Large Margin Cosine Loss for Deep Face Recognition》
论文信息 论文标题:CosFace: Large Margin Cosine Loss for Deep Face Recognition论文作者:H. Wang, Yitong Wang, Zhen ...
- 计网学习笔记七 IP protocol basic
在这一节讲了IP协议的基本内容:包括IPv4提供的操作.数据报在IPv4下是怎么样的结构.数据报是怎样切片发送的.IPv4的编址方式有什么--IPv6在下一节讲网络层协议簇时细讲. IPv4协议的具体 ...
- Atcoder Regular Contest 093 C - Bichrome Spanning Tree
给定一张图,对图上边黑白染色,使得同时选择了两种颜色边的最小生成树边权和为X,求染色方案数. 先求出图的\(mst\)大小,然后分三类讨论: 1.\(X<mst\) 无解 2.\(X==mst\ ...
- SpringBoot项目中使用缓存Cache的正确姿势!!!
前言 缓存可以通过将经常访问的数据存储在内存中,减少底层数据源如数据库的压力,从而有效提高系统的性能和稳定性.我想大家的项目中或多或少都有使用过,我们项目也不例外,但是最近在review公司的代码的时 ...
- day15:递归函数&递归练习题
递归函数 递归函数的定义 : 自己调用自己的函数就是递归 递: 去 归: 回 一去一回就是递归 一个简单的递归例子 # 1.一个简单的递归例子 def digui(n): print(n,& ...
- Yii2批量插入数据
方法一 yii2一次插入多行数据 /** * @inheritdoc 批量添加 * @params $add array 添加数据 */ public function add_all($add) ...
- vue自定义组件——split-pane
pre { overflow-y: auto; max-height: 500px } github地址: https://github.com/lxmghct/my-vue-components 组 ...