数论进阶

扩展欧几里得算法

裴蜀定理(Bézout's identity)

\(1\) :对于任意整数 \(a\),\(b\) ,存在一对整数 \(x\) ,\(y\) ,满足 \(ax+by=GCD(a,b)\) 。

2:对于任意整数 \(a\),\(b\) ,二元一次不定方程 \(ax+by=c\) 有整数解 \((x,y)\) 当且仅当 \(GCD(a,b)|c\) 。

扩展欧几里得算法(Extended Euclidean algorithm)

首先,我们来回顾一下欧几里得算法:

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

扩展欧几里得算法是用于在已知 \(a\),\(b\) 的情况下求一组解 \(x\),\(y\) ,使他们之间满足:\(ax+by=GCD(a,b)=d\)。(GCD即最大公约数)。我们要计算的是 \(a\) 和 \(b\) 的最大公约数,并求出 \(x\) 和 \(y\) 使得 \(ax+by=d\)。

此时,我们已经计算出了下一个状态:\(b\) 和 \((a\%b)\) 的最大公约数,并求出了一组 \(x_1,y_1\) 使得:\(bx_1+(a\%b)y_1=d\) 。而相邻状态之间的关系是怎样的呢?

我们知道:\(a\%b=a-\lfloor{a \over b} \rfloor *b\) ,所以有:

\[\begin{align}
d&=b * x_1 +[a-\lfloor {a\over b} \rfloor *b]*y_1\\
&=b*x_1+a*y_1-\lfloor{a\over b}\rfloor * b * y_1\\
&=a*y_1+b*(x_1-\lfloor {a\over b} \rfloor * y_1)\\
\end{align}
\]

所以:\(x=y_1,y=x_1-\lfloor{a\over b}\rfloor *y_1\) 。

特别的:在欧几里得算法执行到最后一步,即 \(b=0\) 时,我们可以得到一对整数 \(x=1,y=0\) ,使得 \(a*1 + 0*0=GCD(a,0)\) 。

由此便可以写出扩展欧几里得的模板(exGCD),代码如下:

typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y){
if (b==0) {
x=1;
y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}

线性同余方程

乘法逆元

中国剩余定理

扩展中国剩余定理

原根

BSGS

代码如下:

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
int log_mod(ll a,ll b,ll n) {
if (b==1) return 0;
gp_hash_table<int,int> hash;
int t=ceil(sqrt(n));
ll z=1;
for (int i=0; i<t; i++) {
hash[b*z%n]=i;
z=z*a%n;
}
int now=1;
for (int i=1; i<=t; i++) {
now=now*z%n;
if (hash.find(now)!=hash.end()) {
return i*t-hash[now];
}
}
return -1;
}

高次剩余

很遗憾,这个内容作者在OIWIKI上找到,而百度百科上的内容也不全。

为了学习高次剩余部分的内容,我们先给出一个问题:

求解 \(x^a\equiv b (mod\ p)\)

我们规定:\(p\) 是个质数。

在学习了原根方面的知识后,我们可以得知:p一定存在一个原根,我们假设这个原根为 \(g\) 。因此,对于模 \(p\) 意义下的任意的数 \(x(0\le x <p)\) 有且仅有一个数满足 \(i(0 \le i<p-1)\) 满足 \(x=g^i\) 。

接下来将会列出解决方案。

方案一

我们令 \(x=g^c\) ,由于 \(g\) 是 \(p\) 的原根(而这个 \(g\) 和 \(c\) ,通过之前学习的方法,我们一定可以找到),那么问题将转化为求解 \((g^c)^a \equiv b (\mod p)\) ,我们可以在将其变换,得到:

\[(g^a)^c\equiv b(mod\ p)
\]

于是,这就变成了离散对数的基本模型了,我们可以用 \(BSGS\) 解决这道题,只要在 \(O(\sqrt p)\) 内解出 \(c\) ,这样就可以得到原方程的一个特解 \(x_0\equiv g^c (mod\ p)\)

方案二

仍然令 \(x=g^c\) ,此时,我们在规定 \(b=g^t\) ,于是我们得到:

\[g^{ac}\equiv g^t (mod\ p)
\]

方程两边同时取离散对数后得到:

\[ac\equiv t (mod\ \varphi (p))
\]

而方程中的 \(t\) 可以通过 \(BSGS\) 求解 \(g^t \equiv b (mod\ p)\) 得到,于是这就转化成了一个线性同余方程的问题。这样便可解除一个特解 \(c_0\) ,\(c\) 的所有通解为 \(c_0+k\frac {\varphi(p)} {gcd(a,\varphi(p))}\) ,其中 \(k\) 为整数。

于是 \(x\) 的通解为: \(g^{c_0+k\frac {\varphi(p)} {gcd(a,\varphi(p))}}\) ,而我们要求的是所有在 \([0,p-1]\) 范围内的解,可以将解一个个放进 \(vector\) 中,直到重复(可以用 \(set\) 或者 \(hash\) 来判断重复,这里我们采用的是 \(hash\) 的方法,不了解 hash 的读者可以看这里,但我们的 hash 是直接调用的,而不是手写的)

代码如下:

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
vector<int> extract_mod(int a,int b,int p){
vector<int> res;
int g=find_yg(p);
int c=log_mod(pow_mod(g,a,p),b,p);
if (c==-1) return res;
int x=pow_mod(g,c,p),t=pow_mod(g,(p-1)/gcd(a,p-1),p);
gp_hash_table<int,int> hash;
while(1){
res.push_back(x);
hash[x]=1;
x=(ll)x*t%p;
if (hash[x]==1) break;
}
return res;
}

exBSGS

代码如下:

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
int exgcd(int a,int b,int &x,int &y){
if (b==0){
x=1;
y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}
int exBGSG(int a,int b,int n){
if (b==1) return 0;
int cnt=0,x,y;
ll w=1;
while(1){
int d=exgcd(a,n,x,y);
if (d==1) break;
if (b%d!=0) return -1;
b/=d;
n/=d;
w=w*a/d%n;
cnt++;
if (b==w) return cnt;
}
exgcd(w,n,x,y);
b=(ll)b*(x%n+n)%n;
a=a%n;
gp_hash_table<int,int> hash;
int t=ceil(sqrt(n));
ll z=1;
for (int i=0;i<t;i++){
hash[b*z%n]=i;
z=z*a%n;
}
int now=1;
for (int i=1;i<=t;i++){
now=now*z%n;
if (hash.find(now)!=hash.end()){
return i*t-hash[now]+cnt;
}
}
return -1;
}
int main(){ return 0;
}

数论进阶&#160;的更多相关文章

  1. 【数论】数论进阶-Preknowledge

    数论进阶-Preknowledge 参考资料:洛谷网校2018夏季省选基础班SX-3数论进阶课程及课件 一.整除与取整除法 1.1 定义 1.整除 \(\forall~x,y~\in~Z^+,\) 若 ...

  2. ACM进阶计划

    ACM进阶计划ACM队不是为了一场比赛而存在的,为的是队员的整体提高.大学期间,ACM队队员必须要学好的课程有:lC/C++两种语言l高等数学l线性代数l数据结构l离散数学l数据库原理l操作系统原理l ...

  3. “胡”说IC——菜鸟工程师完美进阶

    “胡”说IC——菜鸟工程师完美进阶(数十位行业精英故事分享,顶级猎头十多年来经验总结,对将入或初入IC电子业“菜鸟”职业发展.规划的解惑和点拨.) 胡运旺 编著   ISBN 978-7-121-22 ...

  4. HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!)

    HTML5游戏开发进阶指南(亚马逊星畅销书,教你用HTML5和JavaScript构建游戏!) [印]香卡(Shankar,A.R.)著 谢光磊译 ISBN 978-7-121-21226-0 201 ...

  5. [转]ACM进阶计划

    ACM进阶计划  大学期间,ACM队队员必须要学好的课程有: lC/C++两种语言 l高等数学 l线性代数 l数据结构 l离散数学 l数据库原理 l操作系统原理 l计算机组成原理 l人工智能 l编译原 ...

  6. ACM进阶

    ACM队不是为了一场比赛而存在的,为的是队员的整体提高. 大学期间,ACM队队员必须要学好的课程有: l C/C++两种语言 l 高等数学 l 线性代数 l 数据结构 l 离散数学 l 数据库原理 l ...

  7. Kinect for Windows SDK开发入门(15):进阶指引 下

    Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...

  8. SQL Server 扩展事件(Extented Events)从入门到进阶(1)——从SQL Trace到Extented Events

    由于工作需要,决定深入研究SQL Server的扩展事件(Extended Events/xEvents),经过资料搜索,发现国外大牛的系列文章,作为“学习”阶段,我先翻译这系列文章,后续在工作中的心 ...

  9. 高级进阶DB2(第2版)——内部结构、高级管理与问题诊断

    <高级进阶DB2(第2版)——内部结构.高级管理与问题诊断> 基本信息 作者: 牛新庄    出版社:清华大学出版社 ISBN:9787302323839 上架时间:2013-7-3 出版 ...

随机推荐

  1. NC15975 小C的记事本

    NC15975 小C的记事本 题目 题目描述 小C最近学会了java小程序的开发,他很开心,于是想做一个简单的记事本程序练练手. 他希望他的记事本包含以下功能: 1.append(str),向记事本插 ...

  2. TypeScript let与var的区别

    1.作用域不同 用var声明的变量,只有函数作用域和全局作用域,没有块级作用域.而let可以实现块级作用域,只能在代码块{}内有效,在{}之外不能访问,如下代码所示: { let a = 0; var ...

  3. (一)Linux环境的学习环境的搭建

    我们使用VMWARE来安装Debian11系统来进行我们的LINUX学习 Debian虚拟机的安装 vmware-tools的安装 xShell的安装使用 samba的配置 gcc环境的配置 Debi ...

  4. C++学习日记:关于我决定开始学习C++的那些事

    苦恼于Python运行时感人的速度,我决定学习C++. 为了激励我自己好好地学习这门未曾谋面的编程语言,我决定在此开设专栏:C++学习日记.希望在读者们的监督下,我可以早日掌握这门语言.当然,如果那位 ...

  5. 全民开发!仓库管理者用无代码平台,搭建理想的WMS软件

    货在哪儿? 我说过仓库管理不要依赖"老人",因为只有"他"知道货在哪怎么行?也不要完全依赖"系统",因为当前的"系统"并 ...

  6. VGA显示原理

    VGA显示是图像处理的基础,是一开始广泛使用的显示器,大部分机器采用VGA接口驱动,所以后来的显示器需要用VGA-xxx转接口来匹配. 用FPGA来驱动VGA,并不适用于显示动态(如手机显示,GUI) ...

  7. 算法竞赛进阶指南 0x43 线段树

    目录 线段树简介 线段树的简单代码实现 建树代码 修改操作 查询操作 线段树的查询操作的时间复杂度分析: AcWing245. 你能回答这些问题吗 思路 代码[时间复杂度:\(O( \space(N+ ...

  8. 论文解读(MaskGAE)《MaskGAE: Masked Graph Modeling Meets Graph Autoencoders》

    论文信息 论文标题:MaskGAE: Masked Graph Modeling Meets Graph Autoencoders论文作者:Jintang Li, Ruofan Wu, Wangbin ...

  9. Java语言的跨平台性

    2.1 Java虚拟机 -- JVM JVM:Java虚拟机,简称JVM,是运行所有java程序的假想计算机,是java程序的运行环境,是java最具吸引力的特性之一,我们编写的java代码都运行在J ...

  10. CF383C Propagating tree (线段树,欧拉序)

    \(tag\)没开够\(WA\)了一发... 求出\(dfs\)序,然后按深度分类更新与查询. #include <iostream> #include <cstdio> #i ...