exBSGS算法
BSGS,全称\(Baby Step Giant Step\),是用于求解离散对数的一种算法。
就是用来求\(A^x \equiv B (mod\ p)\) 的x这么一种算法……
理论知识是:在[0,p)之内是一定有解的,因为指数模的周期性。即\(A^x\)对p的模随x变化有周期性,最大周期不超过p。首先,余数只可能有p个元素,所以x取不超过p个值必定出现相同的余数。根据同余的性质,只要找到两个余数相同的,剩下的全部乘以\(A^k,k\)为整数,所以\(A^n \equiv A^{x+n}\)对于所有x都成立。
朴素算法是枚举0~p-1。
如何改进呢?我们考虑把数分组,每组大小为\(n = \sqrt{p}\),每组\(m = \frac{p}{n}\)个数。
对于每组的询问,我们组内的答案可以看作:\(A^{im-y} \equiv B (mod\ p)\)
移项一下就有:\(A^{im} \equiv BA^y (mod\ p)\)
我们枚举\(0~m-1\),计算所有的\(BA^y\),存进hash表,之后枚举\(1~n\)计算\(A^{im}\)的值,在hash表中找答案即可。
时间复杂度\(O(\sqrt{n})\)
然而这个算法只适用于……\(gcd(A,p) = 1\),即二者互质的情况。否则此时\(A^{-1}\)不存在,就不能把答案看作\(A^{im-y}\)
解决的方法是预先处理成二者互质。
我们一直把方程同除\(A,p\)的公约数就行了。如果中途某一次B除不开就是无解的,否则一直除,得到\(B_n = \frac{A^n}{d_1d_2…d^n}A^{x-n} + p_ny\),令\(D = \frac{A^n}{d_1d_2…d^n}\),此时必存在D的逆元,所以式子变为\(A^{x-n} \equiv B_nD^{-1} (mod\ p_n)\),求解即可。
这有个三合一的板子题。
SDOI2011 计算器
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define I inline
using namespace std;
typedef long long ll;
const int M = 200005;
const int mod = 999979;
int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
return ans * op;
}
int T,K,y,z,p;
struct Hash
{
int sta[M],top,head[M<<3],num[M],val[M],nxt[M],ecnt;
void init(){ecnt = 0;while(top) head[sta[top--]] = 0;}
void insert(int x,int y)
{
int h = x % mod;
for(int i = head[h];i;i = nxt[i]) if(num[i] == x) {val[i] = y;return;}
if(!head[h]) sta[++top] = h;
nxt[++ecnt] = head[h],head[h] = ecnt;
num[ecnt] = x,val[ecnt] = y;
}
int query(int x)
{
int h = x % mod;
for(int i = head[h];i;i = nxt[i]) if(num[i] == x) return val[i];
return -1;
}
}H;
int gcd(int a,int b) {return (!b) ? a : gcd(b,a%b);}
int mul(int a,int b,int t){return 1ll * a * b % t;}
int qpow(int a,int b,int t)
{
int g = 1;
while(b)
{
if(b&1) g = mul(g,a,t);
a = mul(a,a,t),b >>= 1;
}
return g;
}
int exgcd(int a,int b,int &x,int &y)
{
if(!b){x = 1,y = 0;return a;}
int d = exgcd(b,a%b,y,x);
y -= a / b * x;
return d;
}
int inv(int a,int b)
{
int x,y;
exgcd(a,b,x,y);
return (x % b + b) % b;
}
int BSGS(int a,int b,int c)
{
int cnt = 0,G,d = 1;
while((G = gcd(a,c)) != 1)
{
if(b % G) return -1;
cnt++,b /= G,c /= G,d = mul(d,a/G,c);
}
b = mul(b,inv(d,c),c);
H.init();
int s = sqrt(c),p = 1;
rep(i,0,s-1)
{
if(p == b) return i + cnt;
H.insert(mul(p,b,c),i),p = mul(p,a,c);
}
int q = p,t;
for(int i = s;i <= c + s - 2;i += s)
{
t = H.query(q);
if(t != -1) return i - t + cnt;
q = mul(q,p,c);
}
return -1;
}
int main()
{
T = read(),K = read();
while(T--)
{
y = read(),z = read(),p = read();
if(K == 1) printf("%d\n",qpow(y,z,p));
if(K == 2)
{
if(z % gcd(y,p)) {printf("Orz, I cannot find x!\n");continue;}
int X,Y;
int d = exgcd(y,p,X,Y);
p /= d;
printf("%d\n",(mul(X,z/d,p) + p) % p);
}
if(K == 3)
{
y %= p,z %= p;
int ans = BSGS(y,z,p);
(ans == -1) ? printf("Orz, I cannot find x!\n") : printf("%d\n",ans);
}
}
return 0;
}
exBSGS算法的更多相关文章
- 关于 BSGS 以及 ExBSGS 算法的理解
BSGS 引入 求解关于\(X\)的方程, \[A^X\equiv B \pmod P \] 其中\(Gcd(A,P)=1\) 求解 我们令\(X=i*\sqrt{P}-j\),其中\(0<=i ...
- 『高次同余方程 Baby Step Giant Step算法』
高次同余方程 一般来说,高次同余方程分\(a^x \equiv b(mod\ p)\)和\(x^a \equiv b(mod\ p)\)两种,其中后者的难度较大,本片博客仅将介绍第一类方程的解决方法. ...
- 数论算法 Plus
好像有不少更新:) 本文主要记录一些不是那么熟悉的高级数论算法的推导与应用. exBSGS算法 解决模数.底数不互质的离散对数问题. (1)为何\(BSGS\)算法不再适用:\(A\)不一定存在逆元, ...
- 【BZOJ2242】[SDOI2011] 计算器(数学模板三合一)
点此看题面 大致题意: 让你完成三种操作:求\(Y^Z\%P\)的值,求满足\(XY\equiv Z(mod\ P)\)的最小非负整数\(X\),求满足\(Y^X\equiv Z(mod\ P)\)的 ...
- POJ 3243 Clever Y Extended-Baby-Step-Giant-Step
题目大意:给定A,B,C,求最小的非负整数x,使A^x==B(%C) 传说中的EXBSGS算法0.0 卡了一天没看懂 最后硬扒各大神犇的代码才略微弄懂点0.0 參考资料: http://quarter ...
- 『正睿OI 2019SC Day7』
简单数论 质因子分解 素性测试 素性测试指的是对一个正整数是否为质数的判定,一般来说,素性测试有两种算法: \(1.\) 试除法,直接尝试枚举因子,时间复杂度\(O(\sqrt n)\). \(2.\ ...
- 省选算法学习-BSGS与exBSGS与二次剩余
前置知识 扩展欧几里得,快速幂 都是很基础的东西 扩展欧几里得 说实话这个东西我学了好几遍都没有懂,最近终于搞明白,可以考场现推了,故放到这里来加深印象 翡蜀定理 方程$ax+by=gcd(a,b)$ ...
- 算法笔记--BSGS && exBSGS 模板
https://www.cnblogs.com/sdzwyq/p/9900650.html 模板: unordered_map<int, int> mp; LL q_pow(LL n, L ...
- 「算法笔记」BSGS 与 exBSGS
一.离散对数 给定 \(a,b,m\),存在一个 \(x\),使得 \(\displaystyle a^x\equiv b\pmod m\) 则称 \(x\) 为 \(b\) 在模 \(m\) 意义下 ...
随机推荐
- Mysql5.6审计功能
1. 前言 为了安全和操作的可追溯性考虑,越来越多的公司增加了审计功能.mysql5.5推出了相关的审计功能,到5.6.20功能进一步完好.算是勉强可用了.尽管细粒度方面做的不是太好. ...
- 如何使用电骡eMule上传资源
1 在电脑中创建一个文件夹专门为上传资源使用 在里面放入任意文件并右击显示ED2K链接 链接效果如下 2 登陆verycd网站,并点击上传资源 复制ED2K地址并选择分类
- WMS8_条码界面操作简要说明(包装作业)
说明:条码界面的主要用途是包装作业 这个客户端,完全是JS实现的 可以从 All operation看板视图 Picking的表单视图 All operatio ...
- vs附加到多个进程调试
我们用vs调试,通常附加到一个进程进行调试,有时候需要同时附加到多个进程. 例如:同时调试客户端与服务端,我们需要同时附加到客户端与服务端进程. 按F5(执行)键调试,程序只要遇到断点就中断. 按F1 ...
- WinDbg加载不同版本CLR
WinDbg调试.net2.0和.net4.0程序有所不同,因为.net4.0使用新版本的CLR.例如: mscoree.dll 变为 mscoree.dll 和 mscoreei.dll, msco ...
- Twitter网站架构分析介绍
http://www.kaiyuanba.cn/html/1/131/147/7539.htm作为140个字的缔造者,twitter太简单了,又太复杂了,简单是因为仅仅用140个字居然使有几次世界性事 ...
- fping - send ICMP ECHO_REQUEST packets to network hosts
NAME fping - send ICMP ECHO_REQUEST packets to network hosts SYNOPSIS fping [ options ] [ systems... ...
- Linux 下编译安装OpenCV(zhuanzai)
http://www.cnblogs.com/emouse/archive/2013/02/22/2922940.html Cmake的安装 OpenCV 2.2以后版本需要使用Cmake生成make ...
- .Net Core表单定义
创建表单 <form asp-controller="Account" asp-action="Login" asp-route-returnurl=&q ...
- 5分钟快速入门Markdown
Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. Markdown的语法简洁明了.学习容易,而且功能比纯文本更强,因此有很多人用它写 ...