BSGS算法及扩展
BSGS算法
\(Baby Step Giant Step\)算法,即大步小步算法,缩写为\(BSGS\)
拔山盖世算法
它是用来解决这样一类问题
\(y^x = z (mod\ p)\),给定\(y,z,p>=1\)求解\(x\)
普通的\(BSGS\)只能用来解决\(gcd(y,p)=1\)的情况
设\(x=a*m+b, m=\lceil \sqrt p \rceil, a\in[0,m), b\in[0,m)\)
那么\(y^{a*m}=z*y^{-b} (mod\ p)\)
怎么求解,为了方便,设\(x=a*m-b\)
那么\(y^{a*m}=z*y^b(mod \ p), a\in(0,m+1]\)
直接暴力辣,把右边的\(b\)枚举\([0,m)\),算出\(z*y^b(mod \ p)\),哈希存起来
然后左边\(a\)枚举\((0, m+1]\),算出\(y^{a*m}(mod \ p)\)查表就行了
然后不知道为什么要用\(exgcd\),只会\(map\)...
代码
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
template <class Int>
IL void Input(RG Int &x){
RG int z = 1; RG char c = getchar(); x = 0;
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
x *= z;
}
IL void None(){
puts("Orz, I cannot find x!");
}
int p;
IL int Pow(RG ll x, RG ll y){
RG ll ret = 1;
for(; y; x = x * x % p, y >>= 1)
if(y & 1) ret = ret * x % p;
return ret;
}
map <int, int> pw;
IL void BSGS(RG int x, RG int y){
pw.clear();
if(y == 1){
puts("0");
return;
}
RG int ans = -1, m = sqrt(p) + 1, xx, s = y;
for(RG int i = 0; i < m; ++i){
pw[s] = i;
s = 1LL * s * x % p;
}
xx = Pow(x, m), s = 1;
for(RG int i = 1; i <= m + 1; ++i){
s = 1LL * s * xx % p;
if(pw.count(s)){
ans = i * m - pw[s];
break;
}
}
if(ans < 0) None();
else printf("%d\n", ans);
}
int T, k, y, z;
int main(RG int argc, RG char* argv[]){
for(Input(T), Input(k); T; --T){
Input(y), Input(z), Input(p);
if(k == 1) printf("%d\n", Pow(y, z));
else if(k == 2){
RG int d = (y % p) ? 1 : p;
if(z % d) None();
else printf("%lld\n", 1LL * Pow(y, p - 2) * z % p);
}
else{
if(y % p) BSGS(y % p, z % p);
else None();
}
}
return 0;
}
扩展BSGS
对于\(gcd(y, p)\ne1\)怎么办?
我们把它写成\(y*y^{x-1}+k*p=z, k\in Z\)的形式
根据\(exgcd\)的理论
那么如果\(y,p\)的\(gcd\)不是\(z\)的约数就不会有解
设\(d=gcd(y,p)\)
那么
\]
递归到\(d=1\)
设之间的所有的\(d\)的乘积为\(g\),递归\(c\)次
令\(x'=x-c, p'=\frac{p}{g},z'=\frac{z}{g}\)
那么
\]
那么\(BSGS\)求解就好了
代码
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
# define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
using namespace std;
typedef long long ll;
template <class Int>
IL void Input(RG Int &x){
RG int z = 1; RG char c = getchar(); x = 0;
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
x *= z;
}
map <int, int> pw;
IL int Gcd(RG int x, RG int y){
return !y ? x : Gcd(y, x % y);
}
IL int Pow(RG ll x, RG ll y, RG int p){
RG ll ret = 1;
for(; y; x = x * x % p, y >>= 1)
if(y & 1) ret = ret * x % p;
return ret;
}
int a, b, p;
IL int EX_BSGS(){
if(b == 1) return 0;
pw.clear();
RG int cnt = 0, t = 1, s, x, m;
for(RG int d = Gcd(a, p); d != 1; d = Gcd(a, p)){
if(b % d) return -1;
++cnt, b /= d, p /= d, t = 1LL * t * a / d % p;
if(b == t) return cnt;
}
s = b, m = sqrt(p) + 1;
for(RG int i = 0; i < m; ++i){
pw[s] = i;
s = 1LL * s * a % p;
}
x = Pow(a, m, p), s = t;
for(RG int i = 1; i <= m; ++i){
s = 1LL * s * x % p;
if(pw.count(s)) return i * m - pw[s] + cnt;
}
return -1;
}
int ans;
int main(RG int argc, RG char* argv[]){
for(Input(a), Input(p), Input(b); a + b + p;){
a %= p, b %= p, ans = EX_BSGS();
if(ans < 0) puts("No Solution");
else printf("%d\n", ans);
Input(a), Input(p), Input(b);
}
return 0;
}
BSGS算法及扩展的更多相关文章
- BSGS算法及其扩展
bsgs算法: 我们在逆元里曾经讲到过如何用殴几里得求一个同余方程的整数解.而\(bsgs\)就是用来求一个指数同余方程的最小整数解的:也就是对于\(a^x\equiv b \mod p\) 我们可以 ...
- BSGS算法学习笔记
从这里开始 离散对数和BSGS算法 扩展BSGS算法 离散对数和BSGS算法 设$x$是最小的非负整数使得$a^{x}\equiv b\ \ \ \pmod{m}$,则$x$是$b$以$a$为底的离散 ...
- BSGS算法总结
BSGS算法总结 \(BSGS\)算法(Baby Step Giant Step),即大步小步算法,用于解决这样一个问题: 求\(y^x\equiv z\ (mod\ p)\)的最小正整数解. 前提条 ...
- BSGS算法+逆元 POJ 2417 Discrete Logging
POJ 2417 Discrete Logging Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4860 Accept ...
- BSGS算法解析
前置芝士: 1.快速幂(用于求一个数的幂次方) 2.STL里的map(快速查找) 详解 BSGS 算法适用于解决高次同余方程 \(a^x\equiv b (mod p)\) 由费马小定理可得 x &l ...
- 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法
BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...
- bzoj2242: [SDOI2011]计算器 && BSGS 算法
BSGS算法 给定y.z.p,计算满足yx mod p=z的最小非负整数x.p为质数(没法写数学公式,以下内容用心去感受吧) 设 x = i*m + j. 则 y^(j)≡z∗y^(-i*m)) (m ...
- 浅谈Manacher算法与扩展KMP之间的联系
首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一 ...
- [BSGS算法]纯水斐波那契数列
学弟在OJ上加了道"非水斐波那契数列",求斐波那契第n项对1,000,000,007取模的值,n<=10^15,随便水过后我决定加一道升级版,说是升级版,其实也没什么变化,只 ...
随机推荐
- c语言之字符输入输出和输入验证
单字符I/O:getchar()和putchar() #include<stdio.h> int main(void) { char ch; while ((ch = getchar()) ...
- react 组件列表
let data=[ [ '同时入选IMDB250和豆瓣电影250的电影', '带你进入不正常的世界', '用电[影]来祭奠逝去的岁月', '女孩们的故事[电影]', '', '使用 App [找电影 ...
- Oracle 不小心删除undo数据文件以及磁盘空间不足导致不能登录的解决办法
在一次测试中,由于导入的数据量过大导致事务一直提交失败因为磁盘空间不够用了,一检查发现是undo表空间不够用,于是重新创建了一个表空间,准备把之前的undo表空间删除,删除时却发现一直删不掉,因为它一 ...
- Jenkins整合SonarQube代码检测工具
借鉴博客:https://blog.csdn.net/kefengwang/article/details/54377055 上面这博客写得挺详细的,挺不错.它这个博客没有提供下载的教程,这个博客提供 ...
- element-ui 源码解析 二
Carousel 走马灯源码解析 1. 基本原理:页面切换 页面切换使用的是 transform 2D 转换和 transition 过渡 可以看出是采用内联样式来实现的 举个栗子 <div : ...
- 【转】Git 代码行统计命令集
查看git上个人代码量 git log --author="username" --pretty=tformat: --numstat | awk '{ add += $1; su ...
- 《笔记》Apache2 mod_wsgi的配置
接手了一台古老的服务器的还使用的是mod_wsgi,所以需要配置一下.其实这里有点怀念,记得当年自己折腾第一个app的时候,还是个什么都不懂的菜鸡.当时用django搜方案的时候,还不知道有uwsgi ...
- qtp 自动化测试---点滴 获取属性性/修改窗体标题
1 GetROProperty获取对应属性值 value url (这里出错了) If Window("新增").WinObject("TRzDBEdit_10" ...
- vue計算屬性
計算屬性:computed 和method的差別:computed是基於它的依賴緩存,只有它的相關依賴發生改變時才會重新獲取值. method是在重新渲染時,函數總會重新調用. comuputed:默 ...
- JS 单线程和事件循环
Js 是单线程,js代码从上到下依次执行,比如我们写了两个函数,肯定是上面的函数先执行,下面的函数后执行.但是这种单线程有一个非常大的问题,那就是遇到耗时的任务,后面的任务只能等待它执行完,才能进行. ...