省选算法学习-BSGS与exBSGS与二次剩余
前置知识
扩展欧几里得,快速幂
都是很基础的东西
扩展欧几里得
说实话这个东西我学了好几遍都没有懂,最近终于搞明白,可以考场现推了,故放到这里来加深印象
翡蜀定理
方程$ax+by=gcd(a,b)$一定有整数解
证明:
因为$gcd(a,b)=gcd(b,a$ $mod$ $b)$
所以假设我们已经求出来了$bx+(a$ $mod$ $b)y=gcd(b,a$ $mod$ $b)$的一组整数解$(p,q)$
因为$a$ $mod$ $b=a-(\lfloor \frac{a}{b} \rfloor \ast b)$
所以$bp+(a-a/b\ast b)q=ax+by$
$b(p-(a/b)q)+aq=ax+by$
所以$x=q,y=(p-(a/b)q)$是一组合法的解
所以我们可以递归$gcd$的过程中倒着算每一层的解
当$b=0$时的解为$x=1,y=0$
BSGS
问题提出
给定$a,b,p$,求最小的$x$,使得$a^x≡b(mod$ $p)$
问题求解
显然这个东西不能直接做
考虑分块的思想
定义$m=sqrt(p)$
设$x=i\ast m - j$
也就是$a^{i\ast m}≡a^j\ast b(mod$ $p)$
那么我们首先把$j=0...m-1$时的$a^j\ast b$插入一个哈希表
然后我们枚举$i$,在哈希表里面查询$a^{i\ast m}$有没有出现过,如果出现过,它最大的$j$是多少
然后就可以在$O(sqrt(p))$的时间内解决这个问题了
放个板子
namespace hash{
ll first[1000010],next[1000010],val[1000010],hash[1000010],mod=926081,cnt=0;
void init(){memset(first,0,sizeof(first));cnt=0;}
void insert(ll w,ll pos){
ll p=w%mod,u;
for(u=first[p];u;u=next[u]){
if(hash[u]==w){val[u]=pos;return;}
if(!next[u]) break;
}
if(!next[u]){
cnt++;
if(!first[p]) first[p]=cnt;
else next[u]=cnt;
val[cnt]=pos;hash[cnt]=w;next[cnt]=0;
}
}
ll find(ll w){
ll p=w%mod,u;
for(u=first[p];u;u=next[u]){
if(hash[u]==w) return val[u];
}
return -1;
}
}
ll qpow(ll a,ll b,ll p){
ll re=1;
while(b){
if(b&1) re=re*a%p;
a=a*a%p;b>>=1;
}
return re;
}
ll gcd(ll a,ll b){
if(b==0) return a;
return gcd(b,a%b);
}
ll bsgs(ll a,ll b,ll p){
if(b==1) return 0;
ll i,j,m=ceil(sqrt((double)p)),tmp=b,cur,base=qpow(a,m,p);
hash::init();
for(j=0;j<m;j++){
hash::insert(tmp,j);
tmp=tmp*a%p;
}
tmp=1;
for(i=m;i<=p;i+=m){
tmp=tmp*base%p;
cur=hash::find(tmp);
if(~cur) return i-cur;
}
return -1;
}
exBSGS
使用BSGS的时候要求$gcd(a,p)=1$,扩展版的exBSGS则不需要
具体操作是这样的:
除掉公约数
假设$tmp=gcd(a,p)$
那么$(y\ast tmp)^x=z\ast tmp(mod$ $q\ast tmp)$
其中$y,z,q$是新设出来的量,$y\ast tmp=a$,$z\ast tmp=b$,$q\ast tmp=p$
这一步可以看出,如果$b$不能整除$gcd(a,p)$,那么一定无解
转化
把等式两边的含$tmp$的东西提取出来,可以得到:
$y^{tmp}=z(mod$ $q)$
然后就可以继续递归下去处理了
代码
namespace hash{
ll first[1000010],val[1000010],hash[1000010],next[1000010],cnt=0,mod=926081;
void init(){memset(first,0,sizeof(first));cnt=0;}
void insert(ll w,ll pos){
ll p=w%mod,u;
for(u=first[p];u;u=next[u]){
if(hash[u]==w){val[u]=pos;return;}
if(!next[u]) break;
}
if(!next[u]){
cnt++;
if(!first[p]) first[p]=cnt;
else next[u]=cnt;
next[cnt]=0;val[cnt]=pos;hash[cnt]=w;
}
}
ll query(ll w){
ll p=w%mod,u;
for(u=first[p];u;u=next[u]){
if(hash[u]==w) return val[u];
}
return -1;
}
}
ll qpow(ll a,ll b,ll p){
ll re=1;
while(b){
if(b&1) re=re*a%p;
a=a*a%p;b>>=1;
}
return re;
}
ll gcd(ll a,ll b){
if(b==0) return a;
else return gcd(b,a%b);
}
ll bsgs(ll a,ll b,ll p){
if(b==1) return 0;//不要忘了特判
ll i,j,tmp=1,d=1,cnt=0;
hash::init();
while((tmp=gcd(a,p))!=1){
if(b%tmp) return -1;
cnt++;b/=tmp;p/=tmp;d=d*(a/tmp)%p;//注意这个d的写法
if(b==d) return cnt;//记得写这个
}
ll m=ceil(sqrt(double(p))),base=qpow(a,m,p);//注意这两个东西一定要写在这里,不要写在while上面
tmp=b;
for(j=0;j<m;j++){
hash::insert(tmp,j);
tmp=(tmp*a)%p;
}
for(i=m;i<=p+m;i+=m){//这里注意p+m,不然的话可能会有少数情况挂掉
d=(d*base)%p;//同时注意这里的tmp相当于是一开始就是上面的d而不是1,也就是一开始要乘上已经除掉的东西
tmp=hash::query(d);
if(tmp!=-1) return i-tmp+cnt;
}
return -1;
}
二次剩余(2019/4/14更新)
什么是二次剩余
考虑一个模意义下的方程:$x^2$ $mod$ $p=n$,其中$n\in [1,p-1]$,不考虑$n=0$时显然有解的情况
若这个方程的未知数$x$有在$[0,p-1]$中的整数解,我们称$n$为模$p$意义下的二次剩余,否则称为非二次剩余
判断是否为二次剩余
下文所有等式省略模意义
这里实际上有一个叫勒让德符号的东西,但是我觉得那玩意儿太麻烦了,就不说他的名字了,但是要知道是这个东西
以下方法仅仅对奇质数有效
由费马小定理,我们知道:$n^{p-1}=1$
那么显然$n^{\frac{p-1}{2}}=1$或者$-1$
那么若$x2=n$,对应上面两种情况,我们分别有$x{p-1}=1$或者$-1$
显然这里再根据费马小定理,$x^{p-1}$ 只能是$1$
所以当$n^{\frac{p-1}{2}}=-1$时,$n$是非二次剩余,否则是二次剩余
在有二次剩余的情况下求解$x$
这个......我懒得写证明了,放a_crazy_czy菊苣的链接在这里
省选算法学习-BSGS与exBSGS与二次剩余的更多相关文章
- 省选算法学习-数据结构-splay
于是乎,在丧心病狂的noip2017结束之后,我们很快就要迎来更加丧心病狂的省选了-_-|| 所以从写完上一篇博客开始到现在我一直深陷数据结构和网络流的漩涡不能自拔 今天终于想起来写博客(只是懒吧.. ...
- 省选算法学习-插头dp
插头dp?你说的是这个吗? 好吧显然不是...... 所谓插头dp,实际上是“基于连通性的状态压缩dp”的简称,最先出现在cdq的论文里面 本篇博客致力于通过几道小小的例题(大部分都比较浅显)来介绍一 ...
- 省选算法学习-回文自动机 && 回文树
前置知识 首先你得会manacher,并理解manacher为什么是对的(不用理解为什么它是$O(n)$,这个大概记住就好了,不过理解了更方便做$PAM$的题) 什么是回文自动机? 回文自动机(Pal ...
- 省选算法学习-dp优化-四边形不等式
嗯......四边形不等式的确长得像个四边形[雾] 我们在dp中,经常见到这样一类状态以及转移方程: 设$dp\left[i\right]\left[j\right]$表示闭区间$\left[i,j\ ...
- BSGS算法学习笔记
从这里开始 离散对数和BSGS算法 扩展BSGS算法 离散对数和BSGS算法 设$x$是最小的非负整数使得$a^{x}\equiv b\ \ \ \pmod{m}$,则$x$是$b$以$a$为底的离散 ...
- DSP算法学习-过采样技术
DSP算法学习-过采样技术 彭会锋 2015-04-27 23:23:47 参考论文: 1 http://wr.lib.tsinghua.edu.cn/sites/default/files/1207 ...
- 算法学习之C语言基础
算法学习,先熟悉一下C语言哈!!! #include <conio.h> #include<stdio.h> int main(){ printf(+); getch(); ; ...
- Python之路,Day21 - 常用算法学习
Python之路,Day21 - 常用算法学习 本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...
- C / C++算法学习笔记(8)-SHELL排序
原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...
随机推荐
- git和svn的混用
服务器上的项目是使用svn进行管理的. 本来本地的项目也是通过svn进行管理的,但是后来使用svn的分支功能进行项目的测试/新功能等等时,总是会出现各种各样的问题,遂转投git. 因为git的分支机制 ...
- WPF与Silverlight对比
1.WPF中控件的肤色可以直接:telerik:StyleManager.Theme=”XXXXX”,不用再导入肤色的dll包.可Silverlight使用系统肤色时,要导入肤色的dll包. WPF引 ...
- SAP标准导出功能 - 删除默认选定格式
我们经常会使用SAP系统的标准功能导出ALV显示的数据,一般会选择电子表格. 选择电子表格之后,需要选择电子表格的具体格式. 选择格式之后点击确定,会弹出保存对话框. 如果在使用这个功能的时候,选择了 ...
- oracle数据库 网页管理360浏览器登录不上
使用谷歌浏览器可以登陆,然后在使用360之类的浏览器 就可以登录了
- Maven - 配置镜像仓库
默认仓库的配置(全球中央仓库): 可以打开maven的安装目录/conf/settings.xml文件,配置镜像,找到如下一段配置,这里默认没有配置任何镜像,但是有一个被注释的配置范例: id: 镜像 ...
- 【c学习-1】
#include<stdio.h> int main(){ int a,b,max; printf("请输入两个整数:"); //格式化输出函数 scanf(" ...
- php集成开发环境xampp的搭建
一:运维闲谈 作为一名linux运维工程师,在确保能够有熟练的服务器的搭建和维护优化技能的前提,还需对自身解决问题方法上做出一番功夫. 如何为自己的运维工作添砖加瓦,自动化运维便变得非常重要,一方面, ...
- zabbix运维监控平台
zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决 ...
- ethereum(以太坊)(六)--整型(int)
pragma solidity ^0.4.20; /* uint8 uint16 ...uint256 int8 int16 int24 ..int256 uint => uint256 int ...
- 【TP5.1】HTML标签自动转义,导致CKEditor保存内容无法正常显示!
问题:使用Thinkphp5.1 开发的时候显示CKEditor保存的内容不符合预期. 希望的样子,肯定是不显示<p><b>等标签,而是下面的样子. 因为刚开始使用TP5.1和 ...