数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)

什么叫高次同余方程?说白了就是解决这样一个问题:

A^x=B(mod C),求最小的x值。



baby step giant step算法

题目条件:C是素数(事实上,A与C互质就可以。为什么?在BSGS算法中是要求a^m在%c条件下的逆元的,如果a、c不互质根本就没有逆元。)

如果x有解,那么0<=x<C,为什么?

我们可以回忆一下欧拉定理:

对于c是素数的情况,φ(c)=c-1

那么既然我们知道a^0=1,a^φ(c)=1(在%c的条件下)。那么0~φ(c)必定是一个循环节(不一定是最小的)。既然是%c,那么B一定是0到c-1之间的一个数。最坏的条件下,a的φ(c)以内次方%c的余数各不相同,0<=x<C时一定存在一个x满足条件。根据抽屉原理,如果在大于c的x中出现一个x值满足条件,那在它以前一定有一个更小的x值满足条件。

BSGS的算法是这样的:

首先取m=sqrt(c)向上取整。(为什么取sqrt(c)?我也不是很懂,是为了算法的效率平衡。)

然后先预处理a的0到m次方。

a^x=b ( %c )
设x=i*m+j;
即: i为x/m,j为x%m。
a^(i*m+j)=b;
b * (a^(-m))^i = a^j ( %c )

先枚举j,把右边存起来(Hash 或者 普通数组,下一步用二分查找)
枚举i,如果左边的数值曾经存储过(b * (a^(-m))^i = a^j),则 x=i*m+j。

求a^(-m):(就是a^m的逆元)

有两种方法:

方法一:根据欧拉定理

设A=a^m,那么A^φ(c)==1(%c)

A^(φ(c)-1)*A==1(%c)

到这里已经可以得到A的逆元为A^(φ(c)-1)。

继续推下去,根据c是素数,φ(c)=c-1

那么A的逆元就是A^(c-2)

方法二:相当于解a^m*x-C*y=1,根据拓展欧几里得出x就是逆元。

BSGS主要就是要注意细节,注意要去重(余数相同时只要取较小的一个)。



拓展BSGS

如果a跟c不互质,那该怎么办?

其实只需要加一小段代码就可以。

首先,我们知道:

A%C=B,那么就是A-C*x=B,如果d=gcd(A,C),且B%d==0,那么(A/d)%(C/d)=B/d是成立的。

那么我们就在A与C仍有不为一的公因数的时候,不断地从a^x中拿出一个a与c约分。过程中如果b%d!=0,那么无解。

LL D=1%C; LL g=0,d;
while(  ( d=gcd(A,C)   )  !=1 )
{
        if(B%d)return -1;
        B/=d;C/=d;
        g++;D=D*(A/d)%C;
}

最后我们的方程就变为了k*a^(x-g) == b‘ (%c‘)

用BSGS解出x后加上g就是答案。

时间: 2024-10-12 11:38:45

数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)的相关文章

【poj2417】baby step giant step

最近在学习数论,然而发现之前学的baby step giant step又忘了,于是去翻了翻以前的代码,又复习了一下. 觉得总是忘记是因为没有彻底理解啊. 注意baby step giant step只能用在b和p互质的情况下,因为只有b和p互质的情况下,b才有mod p下的逆元.(下面要用到逆元) 当b和p不互质,就要处理一下.现在就正在做这么一题,方法以后再写. 求a^(-m)就用到了求逆元了,那么如何求逆元呢?我学了两种方法: ·1:欧拉定理:当a和n互质,a^φ ( n) ≡ 1(mod

HDU 2815 扩展baby step giant step 算法

题目大意就是求 a^x = b(mod c) 中的x 用一般的baby step giant step 算法会超时 这里参考的是http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4 map平衡树查找值 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #include <

HDU 2815 Mod Tree 离散对数 扩展Baby Step Giant Step算法

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2815 题意: 思路:与上题不同,这道题不要求m是素数,是利用扩展Baby Step Giant Step算法求离散对数. 以下转载自:AekdyCoin [扩展Baby Step Giant Step] [问题模型] 求解 A^x = B (mod C) 中 0 <= x < C 的解,C 无限制(当然大小有限制--) [写在前面] 这个问题比较麻烦,目前网络上流传许多版本的做法,不过大部分已近被证明

POJ 2417 Discrete Logging ( Baby step giant step )

Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3696   Accepted: 1727 Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, b

HDU 2815 Mod Tree (扩展 Baby Step Giant Step )

Mod Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 96 Accepted Submission(s): 38   Problem Description   The picture indicates a tree, every node has 2 children.  The depth of the nodes whos

扩展baby step giant step模版

#include <cstdio> #include <cstring> #include <cmath> #include <map> using namespace std; typedef __int64 LL; LL gcd(LL a, LL b) { return b ? gcd(b, a%b) : a; } LL pow_mod(LL a, LL p, LL n) { LL ans = 1; while(p) { if(p&1) { an

Baby Step Gaint Step

给定同余式,求它在内的所有解,其中总是素数. 分析:解本同余式的步骤如下 (1)求模的一个原根 (2)利用Baby Step Giant Step求出一个,使得,因为为素数,所以有唯一解. (3)设,这样就有,其中,那么得到. (4)求出所有的,可以知道一共有个解,我们求出所有的,然后排个序即可. O(sqrt(n))的时间复杂度 BSGS如下(前向星版本) const maxn=200001; type node=record data,next,id:longint; end; type L

高次同余方程模板BabyStep-GiantStep

/************************************* ---高次同余方程模板BabyStep-GiantStep--- 输入:对于方程A^x=B(mod C),调用BabyStep(A,B,C),(0<=A,B,C<=10^9) 输出:无解放回-1,有解放回最小非负整数x 复杂度:O(C^0.5),只与C有关,与A,B的大小无关 ************************************/ typedef long long ll; #define HAS

Git Step by Step – (8) Git的merge和rebase

前面一篇文章中提到了"git pull"等价于"git fetch"加上"git merge",然后还提到了pull命令支持rebase模式,这篇文章就介绍一下merge和rebase之间有什么差别. 由于我们主要是想看看merge跟rebase之间的区别,这里就是用本地仓库的分支进行演示了. merge 其实在介绍分支的那篇文章中已经介绍过了一些分支merge的内容,这里就进行一些补充和总结. 下面我们基于本地一个仓库开始介绍,当前仓库的分支情