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算法的更多相关文章

  1. 关于 BSGS 以及 ExBSGS 算法的理解

    BSGS 引入 求解关于\(X\)的方程, \[A^X\equiv B \pmod P \] 其中\(Gcd(A,P)=1\) 求解 我们令\(X=i*\sqrt{P}-j\),其中\(0<=i ...

  2. 『高次同余方程 Baby Step Giant Step算法』

    高次同余方程 一般来说,高次同余方程分\(a^x \equiv b(mod\ p)\)和\(x^a \equiv b(mod\ p)\)两种,其中后者的难度较大,本片博客仅将介绍第一类方程的解决方法. ...

  3. 数论算法 Plus

    好像有不少更新:) 本文主要记录一些不是那么熟悉的高级数论算法的推导与应用. exBSGS算法 解决模数.底数不互质的离散对数问题. (1)为何\(BSGS\)算法不再适用:\(A\)不一定存在逆元, ...

  4. 【BZOJ2242】[SDOI2011] 计算器(数学模板三合一)

    点此看题面 大致题意: 让你完成三种操作:求\(Y^Z\%P\)的值,求满足\(XY\equiv Z(mod\ P)\)的最小非负整数\(X\),求满足\(Y^X\equiv Z(mod\ P)\)的 ...

  5. POJ 3243 Clever Y Extended-Baby-Step-Giant-Step

    题目大意:给定A,B,C,求最小的非负整数x,使A^x==B(%C) 传说中的EXBSGS算法0.0 卡了一天没看懂 最后硬扒各大神犇的代码才略微弄懂点0.0 參考资料: http://quarter ...

  6. 『正睿OI 2019SC Day7』

    简单数论 质因子分解 素性测试 素性测试指的是对一个正整数是否为质数的判定,一般来说,素性测试有两种算法: \(1.\) 试除法,直接尝试枚举因子,时间复杂度\(O(\sqrt n)\). \(2.\ ...

  7. 省选算法学习-BSGS与exBSGS与二次剩余

    前置知识 扩展欧几里得,快速幂 都是很基础的东西 扩展欧几里得 说实话这个东西我学了好几遍都没有懂,最近终于搞明白,可以考场现推了,故放到这里来加深印象 翡蜀定理 方程$ax+by=gcd(a,b)$ ...

  8. 算法笔记--BSGS && exBSGS 模板

    https://www.cnblogs.com/sdzwyq/p/9900650.html 模板: unordered_map<int, int> mp; LL q_pow(LL n, L ...

  9. 「算法笔记」BSGS 与 exBSGS

    一.离散对数 给定 \(a,b,m\),存在一个 \(x\),使得 \(\displaystyle a^x\equiv b\pmod m\) 则称 \(x\) 为 \(b\) 在模 \(m\) 意义下 ...

随机推荐

  1. can-i-win(好)

    https://leetcode.com/problems/can-i-win/ package com.company; import java.util.*; class Solution { / ...

  2. Android应用开发-小巫CSDN博客客户端开发开篇

    2014年9月8日 八月十五 祝各位中秋节快乐 小巫断断续续花了几个星期的时间开发了这么一款应用——小巫CSDN博客,属于私人定制的这样的一款应用,整个客户端的数据全部来自本人博客,是通过爬取本人博客 ...

  3. CSS3中的动画效果-------Day72

    还记得么,在前面也曾实现过"仅仅用css让div动起来",还记得当时是怎么实现的么,是的,transition,针对的也比較局限,仅仅有旋转角度啊,长宽啊之类的,所以说,与其说是动 ...

  4. 从主机给VM Copy文件

    不能从主机给VM 复制文件,在VM里,setting --->option--->shareFolder-->enable-->add(要share的文件路径) then=== ...

  5. NAT和桥接的区别

    NAT 桥接 NAT相当于是局域网中的局域网,把192.168.21.1当作外网ip,重新划分了一个网关(192.168.33.x) 网桥只是把网络桥接起来,还是原来的网关(192.168.21.x) ...

  6. iOS应用数据存储的经常使用方式

    ios程序中数据数据存储有下列5种方式 XML属性列表(plist)归档 Preference(偏好设置) NSKeyedArchiver归档(NSCoding) SQLite3 Core Data ...

  7. Active Directory组织单位(Organizational Unit)操作汇总

    前言 本章聊Active Directory的组织单位(OU)的新增.修改.移动等操作,使用.NET Framework 为我们提供的System.DirectoryServices程序集. 不积跬步 ...

  8. JavaScript中批量设置Css样式

    设置 input 元素的  属性: document.getElementsByTagName("INPUT")[0].setAttribute("属性",&q ...

  9. poj1125--Floyd

    题解: 有N个股票经济人能够互相传递消息.他们之间存在一些单向的通信路径.如今有一个消息要由某个人開始传递给其它全部人.问应该由哪一个人来传递,才干在最短时间内让全部人都接收到消息. 显然,用Floy ...

  10. 使用C#解决部分Win8.1系统窗体每隔几秒失去焦点的问题

    使用了Win8.1 With Update 1后,发现重新启动系统后,当前激活的窗体总是每隔几秒失去焦点.过0.5~1秒焦点回来.导致输入无法正常工作,严重影响使用心情和效率. 在网上找了非常久,也没 ...