BSGS算法(大小步算法)

$BSGS$ 算法 $Baby\ Steps\ Giant\ Steps$.

致力于解决给定两个互质的数 $a,\ p$ 求一个最小的非负整数 $x$ 使得 $a^x\equiv b(mod\ p)$ 其中 $b$ 为任意正整数,$2≤a<p$,$2≤b<p$

该算法使用的原理与欧拉定理有关,其中$a,\ p$互质

                  $a^{\phi (p)}\equiv 1(mod\ p)$

又因为

                  $a^0\equiv 1(mod\ p)$

所以$0到\phi p$是一个循环节,也就是说该算法最多查找$\phi (p)$次就可以找到答案,否则就无解。

设$x=im-k$其中$0≤k≤m$ 原式变为

                  $a^{im-k}\equiv b(mod\ p)$

两边乘以$a^k$得到

                  $a^{im}\equiv a^kb(mod\ p)$

然后我们可以拆成左右两部分分别进行枚举$i$和$k$。

①先枚举$k$,把对应的结果$a^kb$和对应的$k$放入$map$中,$map\_name[a^kb]=k$。$(k\ from\ 0\ to\ m)$

②然后枚举$i$,把得到的结果$a^{im}$在$map$中进行查找,如果$map\_name.count(a^{im})$可以找到,则输出此时的$im-k$即可。($i\ from\ 1\ to\ m$)

如果超出查找范围还没找到,则无解。

这里注意下,对$a^{im}$枚举时,要先快速幂预处理出来$a^m$,然后枚举$i$即可。

算法时间复杂度为$O(max(m, \phi (p)/m))$.

最坏情况为$p$为质数$\phi (p)=p-1$

此时将$m$取$\sqrt p$为最小,时间复杂度为$O(\sqrt p)$。

$m$取$\sqrt p+1$或$ceil(\sqrt p)$。

例题:P3846 [TJOI2007]可爱的质数

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int n, p, b;

unordered_map<ll, int> vis;
inline ll fp( ll a, ll b ){
    a %= p;
    ll res = 1;
    while( b ){
        if( b&1 ) res = res*a%p;
        b >>= 1;
        a = a*a%p;
    }
    return res;
}

int main()
{

    ios::sync_with_stdio(0);

    cin.tie(0); cout.tie(0);
    cin >> p >> b >> n;
    ll m = ceil(sqrt(p));   /*算法复杂度O( max(m, phi(p)/m) ) 所以m取ceil(sqrt(p))最快O(sqrt(p)) */
    ll tmp = n;
    for( int k=0; k<=m; k++,(tmp*=b)%=p ){
        vis[tmp] = k;
    }
    ll t = fp(b, m); tmp = t;
    bool flag = 0;
    for( int i=1; i<=m; i++, tmp=tmp*t%p ){
        if( vis.count(tmp) ){
            flag = 1;
            cout << i*m-vis[tmp] << endl;
            break;

        }
    }
    if(!flag) cout << "no solution" <<endl;

    return 0;
}

原文地址:https://www.cnblogs.com/WAautomaton/p/12048212.html

时间: 2024-08-29 03:43:26

BSGS算法(大小步算法)的相关文章

BSGS(大小步)算法

BSGS算法主要用于求解形如ax≡b(mod p)的式子中x的值. 在这里我们不妨设 x=k1*n-k2 这时我们就可以将式子转化为 ak1*n≡b*ak2(mod p) 这里的n我们设为√p,所以我们利用分块的思想在块数范围内枚举k1即可.那在考虑完k1和n之后我们再考虑一下如何找到k2,我们建立一个哈希表,将k2取0~n时的式子左边的值模p然后将其映射到此时k2的取值.求最后答案时我们只需找到在k1最小时满足条件的最大的k2即可. 模板(poj2417) #include<iostream>

BSGS算法(大步小步算法)

计算\(y^x ≡ z \ mod\ p\) 中 \(x\) 的解. 这个模板是最小化了\(x\) , 无解输出\(No \ Solution!\) map<ll,ll>data; ll m,res,t,ans; bool flag; Pow(int x,int y,int p){return (x^y)%p;} IL void BSGS(RG ll y , RG ll z,RG ll p){ y %=p; flag = false; if(!y && !z){puts(&qu

大数据算法(一)亚线性算法

来源:大数据算法 王宏志 一.概述 大数据定义:在给定的资源约束下,以大数据为输入,在给定时间约束内可以生成满足给定约束结果的算法. 大数据特点:4V 大数据算法可以不是: 精确算法 内存算法 串行算法 仅在电子计算机上运行的算法 大数据算法不仅是: 云计算 MapReduce 大数据分析和挖掘的算法 难度: 访问全部数据时间过长 读取部分数据 亚线性算法 数据难以放入内存 将数据存储到磁盘上 外存算法 仅基于少量数据进行计算 空间亚线性算法 单个计算机难以保存全部数据 并行处理 并行算法 计算

BSGS算法学习小记(大步小步算法)

简介 先看一个式子xy≡z(modp),z是质数 现在只知道x和z,要求y. 大步小步算法(BSGS,Baby Steps Giant Steps)就是解决这个问题. 算法流程 暴搜的枚举范围 根据费马小定理:xz?1≡1. 如果y已经枚举到了z-1了,继续枚举的话就会产生循环. 所以,在暴搜中y的枚举范围就是0--z-1. 如何优化暴搜 我们想一想可不可以用分块来解决枚举的y. 把y分成p?1????√分别枚举行不行? 设m=p?1????√,y=a?m+b,这样枚举a和b就相当于分块枚举了.

【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128 大水题一道 使用大步小步算法,把数字的运算换成矩阵的运算就好了 矩阵求逆?这么基础的线代算法我也不想多说,还是自行百度吧 需要注意的是矩阵没有交换律,所以在计算$B\cdot A^{-m}$的时候不要把顺序搞混 代码: 1 #include <cstring> 2 #include <cstdio> 3 #include <algorithm> 4 #inc

算法大神之路----排序(冒泡排序法)

冒泡排序法 冒泡排序法又称为交换排序法,是由观察水中冒泡变化构思而成,气泡随着水深压力而改变.气泡在水底时,水压最大,气泡最小,而气泡慢慢浮上水面时,气泡所受压力最小,体积慢慢变大. 冒泡排序比较方式是从第一个元素开始,比较相邻的元素大小,如果大小顺序有误,则对调后进行下一个元素比较.直到所有元素满足关系为止. 冒泡排序法分析 冒泡排序法平均情况下,需要比较(n-1)/2次,时间复杂度为O(n2),最好的情况只需要扫描一次,不用操作,即作n-1次比较,时间复杂度为O(n). 由于冒泡排序为相邻两

数据挖掘十大经典算法

一. C4.5  C4.5算法是机器学习算法中的一种分类决策树算法,其核心算法是ID3 算法.   C4.5算法继承了ID3算法的优点,并在以下几方面对ID3算法进行了改进: 1) 用信息增益率来选择属性,克服了用信息增益选择属性时偏向选择取值多的属性的不足: 2) 在树构造过程中进行剪枝: 3) 能够完成对连续属性的离散化处理: 4) 能够对不完整数据进行处理. C4.5算法有如下优点:产生的分类规则易于理解,准确率较高.其缺点是:在构造树的过程中,需要对数据集进行多次的顺序扫描和排序,因而导

8大排序算法图文讲解

排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等. 本文将依次介绍上述八大排序算法. 算法一:插入排序 插入排序示意图 插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入. 算法步骤: 1)将第一待排序序列第一

动态展示十大经典算法

算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序n个项目要Ο(nlogn)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(nlogn)算法更快,因为它的内部循环(innerloop)可以在大部分的架构上很有效率地被实现出来. 快速排序使用分治法(Divideandconquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1.从数列中挑出一个元素,称为“基准”(pivot),