博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
与数论的厮守03:大步小步算法
阅读量:5758 次
发布时间:2019-06-18

本文共 1940 字,大约阅读时间需要 6 分钟。

  这是个名字很新奇的算法。它用来求方程axΞb(mod c)的最小非负整数解,其中ac互质。

  先看欧拉定理:aΦ(c)Ξ1(mod c)。所以x肯定在0~Φ(c)-1里面。所以我们可以考虑枚举x。但显然会超时。

  大步小步算法将我们的暴力枚举变得更加优雅了些。它的步骤是:把0~c-1分成m=√Φ(c)块,然后把a0,a1,a2...am mod c存进去。这里有两种思路,一种是hash,另一种是有序数组加二分,差异不大。如果有解,x就可以表示成i*m+j的形式。于是我们枚举i,ai*m+j=(ai)m*ajΞb(mod c),再分别求出(ai)m mod c和aj mod c即可。怎么求呢?(ai)m容易得到,所以我们来看aj mod c。

    1.扩展欧几里得。先求出u=(ai)m,方程就变为ajΞb/u(mod c),然后扩欧即可。

    2.欧拉定理。v=aj mod c=aΦ(c)-i*m*b mod c,因为ac互质,所以v唯一。

  显然第二种更简单。求出v之后,我们再去之前的有序数组或者hash表里面查找最小的j使得aj mod c = v,若找到了答案就为i*m+j,否则无解。

  时间复杂度为O(clogc)。

  下面是UVA10225 Discrete Logging的代码。注:题中的c为素数,2≤a,b≤c-1,2≤c≤2^31-1所求方程为axΞb(mod c)

#include 
#include
#include
#define maxn 1000010using namespace std;pair
re[maxn];inline long long find(long long l, long long r, long long x){ long long mid; while(l != r){ mid = (l + r) >> 1; if(re[mid].first < x) l = mid + 1; else r = mid; } return re[l].first == x ? l : -1;}inline long long pow(long long a, long long b, long long c){ long long ans = 1; while(b){ if(b & 1) ans = (long long) ans * a % c; a = (long long) a * a % c; b >>= 1; } return ans;}inline long long solve(long long a, long long b, long long c){ long long m = (double)(sqrt(c - 1) + 0.5); re[0].second = 0, re[0].first = 1; for(long long i = 1; i < m; i++) re[i].second = i, re[i].first = re[i - 1].first * a % c; sort(re, re + m); for(long long i = 0; i <= m; i++){ long long v = (long long)pow(a, c - 1 - i * m, c) * b % c; long long j = find(0, m - 1, v); if(~j) return (long long)i * m + re[j].second; } return -1;}int main(){ long long a, b, c; scanf("%lld %lld %lld", &c, &a, &b); long long ans = solve(a, b, c); if(~ans) printf("%lld\n", ans); else puts("no solution"); return 0;}

 

转载于:https://www.cnblogs.com/akura/p/10715401.html

你可能感兴趣的文章
sql server 触发器
查看>>
[工具]前端自动化工具grunt+bower+yoman
查看>>
关于完成生鲜电商项目后的一点总结
查看>>
noip2012 普及组
查看>>
第二阶段 铁大Facebook——十天冲刺(10)
查看>>
Java判断是否为垃圾_Java GC如何判断对象是否为垃圾
查看>>
多项式前k项和java_多项式朴素贝叶斯softmax改变
查看>>
java数组只能交换0下标和n_编程练习-只用0交换排序数组
查看>>
centos7安装mysql视频教程_centos7安装mysql(完整)
查看>>
php图片赋值,php如何优雅地赋值
查看>>
【探索HTML5第二弹01】HTML5的前世今生以及来世
查看>>
Failed to connect to remote VM. Connection refused. Connection refused: connect
查看>>
freeze
查看>>
SAP HANA存储过程结果视图调用
查看>>
设计模式 ( 十八 ):State状态模式 -- 行为型
查看>>
OracleLinux安装说明
查看>>
nova分析(7)—— nova-scheduler
查看>>
Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)
查看>>
OpenMediaVault 搭建git,ssh无法连接问题
查看>>
java多线程之:Java中的ReentrantLock和synchronized两种锁定机制的对比 (转载)
查看>>