数论进阶 
数论进阶
扩展欧几里得算法
裴蜀定理(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\) ,所以有:
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)\) ,我们可以在将其变换,得到:
\]
于是,这就变成了离散对数的基本模型了,我们可以用 \(BSGS\) 解决这道题,只要在 \(O(\sqrt p)\) 内解出 \(c\) ,这样就可以得到原方程的一个特解 \(x_0\equiv g^c (mod\ p)\)
方案二
仍然令 \(x=g^c\) ,此时,我们在规定 \(b=g^t\) ,于是我们得到:
\]
方程两边同时取离散对数后得到:
\]
而方程中的 \(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;
}
数论进阶 的更多相关文章
- 【数论】数论进阶-Preknowledge
数论进阶-Preknowledge 参考资料:洛谷网校2018夏季省选基础班SX-3数论进阶课程及课件 一.整除与取整除法 1.1 定义 1.整除 \(\forall~x,y~\in~Z^+,\) 若 ...
- ACM进阶计划
ACM进阶计划ACM队不是为了一场比赛而存在的,为的是队员的整体提高.大学期间,ACM队队员必须要学好的课程有:lC/C++两种语言l高等数学l线性代数l数据结构l离散数学l数据库原理l操作系统原理l ...
- “胡”说IC——菜鸟工程师完美进阶
“胡”说IC——菜鸟工程师完美进阶(数十位行业精英故事分享,顶级猎头十多年来经验总结,对将入或初入IC电子业“菜鸟”职业发展.规划的解惑和点拨.) 胡运旺 编著 ISBN 978-7-121-22 ...
- HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!)
HTML5游戏开发进阶指南(亚马逊星畅销书,教你用HTML5和JavaScript构建游戏!) [印]香卡(Shankar,A.R.)著 谢光磊译 ISBN 978-7-121-21226-0 201 ...
- [转]ACM进阶计划
ACM进阶计划 大学期间,ACM队队员必须要学好的课程有: lC/C++两种语言 l高等数学 l线性代数 l数据结构 l离散数学 l数据库原理 l操作系统原理 l计算机组成原理 l人工智能 l编译原 ...
- ACM进阶
ACM队不是为了一场比赛而存在的,为的是队员的整体提高. 大学期间,ACM队队员必须要学好的课程有: l C/C++两种语言 l 高等数学 l 线性代数 l 数据结构 l 离散数学 l 数据库原理 l ...
- Kinect for Windows SDK开发入门(15):进阶指引 下
Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...
- SQL Server 扩展事件(Extented Events)从入门到进阶(1)——从SQL Trace到Extented Events
由于工作需要,决定深入研究SQL Server的扩展事件(Extended Events/xEvents),经过资料搜索,发现国外大牛的系列文章,作为“学习”阶段,我先翻译这系列文章,后续在工作中的心 ...
- 高级进阶DB2(第2版)——内部结构、高级管理与问题诊断
<高级进阶DB2(第2版)——内部结构.高级管理与问题诊断> 基本信息 作者: 牛新庄 出版社:清华大学出版社 ISBN:9787302323839 上架时间:2013-7-3 出版 ...
随机推荐
- 【Nim 游戏】 学习笔记
前言 没脑子选手随便一道博弈论都不会 -- 正文 Nim 游戏引入 这里给出最简单的 \(Nim\) 游戏的题目描述: \(Nim\) 游戏 有两个顶尖聪明的人在玩游戏,游戏规则是这样的: 有\(n\ ...
- Thread类的常用方法_获取线程名称的方法和设置线程名称的方法
Thread类的常用方法 获取线程的名称: 1.使用Thread类中的方法getName() String getName() 返回该线程的名称 2.可以先获取到当前正在执行的线程,使用线程中的方法g ...
- P1494 小Z的袜子 莫队
题干 就是将$add$和$del$函数里的$ans$变化变成组合数嘛, 先预处理出$x$只相同袜子一共有$f[x] = 1+2+...+$$(x-1)$种组合, 要注意,由于$f[x]$是一直加到$x ...
- C语言项目实现顺序表
#include <stdio.h> #include <stdlib.h> #include "test_顺序表声明.h" /* run this pro ...
- springboot java -jar指定启动的jar外部配置文件
Limited Setting Effect 中文描述 Java 8 -Xbootclasspath:<path> Sets the search path for bootstrap c ...
- IDEA快捷键之html篇-1
前端IDE中Emmet插件快捷输入HTML代码 前端IDE如VSCode.Atom.Sublime Text和Intellij Idea中使用Emmet插件快捷输入HTML代码的介绍 前端IDE中 ...
- 基于cornerstone.js的dicom医学影像查看浏览功能
最近由于项目需求,需要医学影像.dcm文件的预览功能,功能完成后,基于原生Demo做一个开源分享. 心急的小伙伴可以先看如下基于原生js的全部代码: 一.全部代码 <!DOCTYPE html& ...
- Nginx 的基本概念
Nginx 简介 什么是 Nginx Nginx 是一个高性能的 HTTP 和 反向代理 web服务器 占用内存少,并发能力强,高性能,热部署 但不支持 Java,Java 得配合 tomcat 使用 ...
- python在管道中执行命令
简介 在实际开发中,可能在执行命令过程中,需要在命令的管道中输入相应命令后继续执行,因此需要在执行命令后在命令的管道中输入相应指令 方法一 直接使用communicate向管道传入所需指令,注意如果是 ...
- YII地址切换
以/开头表示跳出当前控制器 例如 return $this->render('/code/login'// 跳出当前控制器,进入Code下login视图 ,['model' => $mod ...