高次同余方程 $BSGS$
第一篇\(Blog\)...
还是决定把\(luogu\)上的那篇搬过来了。
BSGS,又名北上广深
它可以用来求\(a^x \equiv b (mod \ n)\)这个同余方程的一个解,其中\(a,n\)互质。
欧拉定理告诉我们,这里\(a^{\varphi(n)} \equiv 1 (mod \ n)\)
由于\(a^0 \equiv 1 (mod \ n)\),所以这里\(x\)到\(\varphi(n)\)后\(a^x \ mod \ n\)就开始循环了。
所以我们最坏情况就是\(n\)为素数时,从\(0\)到\(n-1\)枚举\(x\)就行了。
这样我们就得到了一个\(O(n)\)复杂度的优秀算法。
然而\(n < 2^{31}\)......
我们考虑让\(x = im - j(0 \le j \le m)\),即把\(0...n-1\)这\(n\)个数按每块大小为\(m\)分块。
就有
\]
两边同时乘\(a^j\)得
\]
对于等式右边,总共只会有\(m+1\)种不同的\(j\),我们把\(ba^0,ba^1,...,ba^m\)全塞到一个\(map\)里,\(i\)也只会有\(\lceil \frac{n}{m} \rceil\)种取值,直接暴力。
最后复杂度为\(O(m + \lceil\frac{n}{m} \rceil)\)
取\(m = \lceil \sqrt{n} \rceil\),就可以做到\(O(\sqrt{n})\)
当然,用\(map\)的话还要乘上一个\(log\)。
其实分块的时候\(j\)取到\(m\)可能会导致有些\(x\)被考虑到两次,但并不影响,而且边界还不怎么需要处理。
贴一下Luogu P3846(板子题)的代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int fpow(int a, int b, int c){
int ret = 1;
for (a %= c; b; b>>=1, a = 1ll*a*a % c) if (b&1) ret = 1ll * ret * a % c;
return ret;
}
int BSGS(int a, int b, int n, int &ret) {
int m = ceil(sqrt(n));
map<int,int> h;
for (int i = 0, tmp = b%n; i <= m; i++, tmp = 1ll*tmp*a%n)
h[tmp] = i;
a = fpow(a, m, n);
for (int tmp = a, i = 1; i <= m; i++, tmp = 1ll*tmp*a%n)
if (h.count(tmp)) { ret = 1ll*i*m - h[tmp]; return 1; }
return 0;
}
int main(){
int a, b, n, flg, ans; scanf("%d%d%d", &n, &a, &b);
flg = BSGS(a, b, n, ans);
if (!flg) puts("no solution"); else printf("%d\n", ans);
return 0;
}
还有比较毒瘤的就是如果\(a \equiv 0 (mod \ n)\)的时候,需要特判\(b \not\equiv 0 (mod \ n)\)
因为如果\(a\)是\(n\)的倍数,那怎么乘都是\(0\)...
所以板子在这里:
int BSGS(int a, int b, int n, int &ret) {
a %= n, b %= n;
if (a == 0) { if (b == 0) { ret = 0; return 1; } else return 0; }
int m = ceil(sqrt(n)); map<int,int> h;
for (int tmp = b%n, i = 0; i <= m; i++, tmp = 1ll*tmp*a % n) h[tmp] = i;
a = fpow(a, m, n);
for (int tmp = a%n, i = 1; i <= m; i++, tmp = 1ll*tmp*a % n)
if (h.count(tmp)) { ret = 1ll*i*m - h[tmp]; return 1; }
return 0;
}
\(ExBSGS\)的话。。。改天学吧 感觉也没什么用
高次同余方程 $BSGS$的更多相关文章
- ACM_高次同余方程
/*poj 3243 *解决高次同余方程的应用,已知 X^Y = K mod Z, 及X,Z,K的值,求 Y 的值 */ #include<cstdio> #include<cstr ...
- 数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)
什么叫高次同余方程?说白了就是解决这样一个问题: A^x=B(mod C),求最小的x值. baby step giant step算法 题目条件:C是素数(事实上,A与C互质就可以.为什么?在BSG ...
- HDU1452Happy 2004(高次幂取模+积性函数+逆元)
题目意思:2004^x的所有正因数的和(S)对29求余:输出结果: 原题链接 题目解析:解析参照来源:点击打开链接 因子和 6的因子是1,2,3,6; 6的因子和是s(6)=1+2+3+6=12; 2 ...
- 【解高次同余方程】51nod1038 X^A Mod P
1038 X^A Mod P 基准时间限制:1 秒 空间限制:131072 KB 分值: 320 X^A mod P = B,其中P为质数.给出P和A B,求< P的所有X. 例如:P = 11 ...
- 『高次同余方程 Baby Step Giant Step算法』
高次同余方程 一般来说,高次同余方程分\(a^x \equiv b(mod\ p)\)和\(x^a \equiv b(mod\ p)\)两种,其中后者的难度较大,本片博客仅将介绍第一类方程的解决方法. ...
- 数论算法 剩余系相关 学习笔记 (基础回顾,(ex)CRT,(ex)lucas,(ex)BSGS,原根与指标入门,高次剩余,Miller_Rabin+Pollard_Rho)
注:转载本文须标明出处. 原文链接https://www.cnblogs.com/zhouzhendong/p/Number-theory.html 数论算法 剩余系相关 学习笔记 (基础回顾,(ex ...
- 51Nod1039 N^3 Mod P 数论 原根 BSGS
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1039.html 题目传送门 - 51Nod1039 题意 题解 这题我用求高次剩余的做法,要卡常数. ...
- 51Nod1038 X^A Mod P 数论 原根 BSGS
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1038.html 题目传送门 - 51Nod1038 题意 题解 在模质数意义下,求高次剩余,模板题. ...
- CF1106F Lunar New Year and a Recursive Sequence 原根、矩阵快速幂、BSGS
传送门 好久没写数论题了写一次调了1h 首先发现递推式是一个乘方的形式,线性递推和矩阵快速幂似乎都做不了,那么是否能够把乘方运算变成加法运算和乘法运算呢? 使用原根!学过\(NTT\)的都知道\(99 ...
随机推荐
- 深入理解 C# 协变和逆变 (转载)
深入理解 C# 协变和逆变 msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型. “逆变”则是指能够使用派生程度更小的类型. 解释的很正确,大致就是这样,不过不 ...
- django-redis和redis连接
redis连接 简单连接 import redis r = redis.Redis(host=) r.set('foo', 'Bar') print r.get('foo') 连接池 import r ...
- java 十大经典排序算法
十大排序算法可以说是每个程序员都必须得掌握的了,花了一天的时间把代码实现且整理了一下,为了方便大家学习,我把它整理成一篇文章,每种算法会有简单的算法思想描述,为了方便大家理解,我还找来了动图演示:这还 ...
- P1059 C语言竞赛
P1059 C语言竞赛 转跳点:
- centos下离线安装zip和unzip
首先如果你的centos可以联网,那可以不用看了,直接yum install -y zip unzip就行,非常的痛快! 如果不能联网,像我一样,只能用vpn连上去,做了点限制.那就非常烦了,yum了 ...
- DB2的简单操作
转 最近在看db2,边读边写了一些,记下来,虽然写的乱七八糟.以备后用. 这些都写的很简单.我觉得也算是一些简单的操作吧,有些也是摘自别人的blog具体是引用哪的就不太记得了. 一.DB2两种注释写法 ...
- 用BusyBox制作Linux最小系统
1.下载busybox-1.30.1 地址:https://busybox.net/downloads/busybox-1.30.1.tar.bz2 2.解压:tar xvf busybox-1.30 ...
- JS浮点数的研究
为什么0.1 + 0.2 得到的是 0.30000000000000004 console.log( 0.1 + 0.2 == 0.3);//false 在js中所有的整数和小数都是以Number形式 ...
- 002.让CI4框架CodeIgniter显示错误信息
01. 在public目录的index.php中,添加以下内容: //定义环境为开发模式,可以输出各种错误信息 define('ENVIRONMENT', 'development'); 02.我们在 ...
- 007.Delphi插件之QPlugins,插件的卸载和重新加载
效果图如下,可以反复卸载和重新加载.QPlugins这个插件,还没弄明白,摸索着跟着DEMO写 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows ...