BSGS算法

BSGS算法用于求解关于x的模方程\(A^x\equiv B\mod P\)(P为质数),相当于求模意义下的对数。

思想:

由费马小定理,\(A^{p-1}\equiv 1\mod P\),在p-1次方后开始循环,所以若原方程有解,\(x_{min}\in[0,P-1]\)。

设\(x=i*m+j\),有\(A^{i*m+j}\equiv B\mod P\),移项得\({(A^m)}^i\equiv B*A^{-j}\mod P\),类似天天爱跑步,对于左右互不影响的等式可以开桶统计。例如可以枚举i,检查另一侧是否有对应的j满足条件。

实现时,先把一侧的值存入map或hash表,再在另一侧枚举。写成\(x=i*m-j\)的形式,可以避免求逆元。

时间复杂度:\(j\in[0,m-1]\),\(i\in [0,\frac p m]\),复杂度为\(O(\max(m,\frac p m))\),当\(m=\sqrt p\)时取最优,为\(O(\sqrt p)\)。

细节:

  1. 特判A==0的情况。
  2. 写成\(x=i*m-j\),j从0枚举到m,i从1枚举到m,因为\(0=1*m-m\)。
  3. 枚举j时,如果模出结果相同,在hash表中用大的j覆盖小的j,因为\(x=i*m-j\),显然j越大x越小。
  4. 传入时A、B先模P。

Code(POJ2417 Discrete Logging):

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Mod=20180801,N=3e7+5;
struct Hashtable{
int size,key[N],nxt[N],head[N];
ll val[N];
inline void clear(){
memset(head,0,sizeof(head));
size=0;
}
inline int hash(ll Key){
return Key%Mod;
}
inline ll find(ll Key){
for(int i=head[hash(Key)];i;i=nxt[i]) if(key[i]==Key) return val[i];
return -1;
}
inline void insert(ll Key,ll Val){
for(int i=head[hash(Key)];i;i=nxt[i]) if(key[i]==Key) return (void) (val[i]=Val);
key[++size]=Key;val[size]=Val;nxt[size]=head[hash(Key)];head[hash(Key)]=size;
}
}mp;
ll qpow(ll a,ll b,ll p){
ll res=1;
for(;b;b>>=1,a=a*a%p) if(b&1) res=res*a%p;
return res%p;
}
ll BSGS(ll a,ll b,ll p){
if(a==0) return b==0?1:-1;
mp.clear();
ll M=ceil(pow(p*1.0,0.5)),t=1,s=qpow(a,M,p),k;
for(int i=0;i<=M;++i) mp.insert(b,i),b=b*a%p;
for(int i=1;i<=M;++i) if(t=t*s%p,(k=mp.find(t))!=-1) return i*M-k;
return -1;
}
int main(){
ll a,b,p,ans;
while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF) {
ans=BSGS(a%p,b%p,p);
ans==-1?puts("no solution"):printf("%lld\n",ans);
}
return 0;
}

最新文章

  1. 软件测试之loadrunner学习笔记-01事务
  2. C#版 Socket编程(最简单的Socket通信功能)
  3. php连接多数据库
  4. 利用sourcemap来调试sass
  5. Quartz 并发/单线程
  6. Socket 学习(三).3 TCP UDP 图解
  7. STM32F103RC进入串口3接收中断产生HardFault_Hander问题解决!
  8. Docker 学习7 Dockerfile详解
  9. [Swift]LeetCode1032. 字符流 | Stream of Characters
  10. Flask--路由, 配置, 蓝图
  11. sqlserver waitfor time 延迟函数的用法
  12. ARTIFICIAL INTELLIGENCE FOR GAMES (Ian Millington / John Funge 著)
  13. SSH, 整合分页功能,连带DAO经典封装
  14. CMake 示例
  15. 大文件拆分方案的java实践(附源码)
  16. Java 简单的rpc 一
  17. [Umbraco] 项目结构
  18. 浅谈TCP/IP(new 常见面试问题)
  19. .net HttpCrawler
  20. 苹果开发小记(一):NSString 的比较用法

热门文章

  1. 微信小程序 原生框架 (分享方法封装)
  2. R330 打印机连供墨水红灯常量处理
  3. 洛谷P1855 榨取kkksc03 [2017年4月计划 动态规划 09]
  4. 怎么让一个不定宽高的div垂直水平居中?
  5. BootStrap 栅格化换行问题
  6. 【教程】5分钟在PAI算法市场发布自定义算法
  7. android rsa 示例
  8. python中接受任意关键字的参数
  9. Latex 出现编辑公式,出现错误 !pdfTex error: Font rntxmi7 at 438 not found
  10. 【JZOJ5060】【GDOI2017第二轮模拟day1】公路建设 线段树+最小生成树