离散对数求解算法

2024-05-10 22:32
文章标签 算法 求解 离散 对数

本文主要是介绍离散对数求解算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


求解一个最小的x满足给定的方程Bx == N (mod P)

使用baby_step_giant_step算法。也就是先小步后大步算法。

1、令x=i*m+j  (m=ceil(sqrt(p))),

那么原式化为 B^(i*m)*B^j==N(MOD P)

B^j==N*B^(-i*m)(MOD P)---------->B^j==N*B^m^(-i)(MOD P)

2、先预处理B^0,B^1,B^2……B^(m-1),存入HASH表,我使用结构体排序然后二分查找,这一步就是baby_step,每次移动1

3、然后快速幂求出B^-m,枚举i,如果存在N*B^(-i*m)存在于HASH表中,说明存在解x=i*m+j,这一步为giant_step,每次移动m

注意以上解法是最基本的,只能对于gcd(B,P)==1,算法的时间复杂度是O(sqrt(P)*log(sqrt(P)))

样题:poj2417

ps:参考cxlove博客,密码学里面貌似叫做shanks算法 点击打开链接

模板:

///大步小步算法
struct baby///小步算法预存的结构体定义
{
    long long b,j;
    bool operator < (const baby &other)const{
        if(b==other.b)return j<other.j;
        return b<other.b;
    }
}babyv[100005];
///快速幂,x^y%mod
long long q_pow(long long x,long long y,long long mod)
{
    long long ans=1;
    while(y>0)
    {
        if(y&1)ans=(ans*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return ans;
}
///小步预存的个数为m的结构体里面查找num
long long find(long long num,long long m)
{
    long long l=0,r=m-1,ans=-1;
    while(r>=l)
    {
        long long mid=(r+l)/2;
        if(babyv[mid].b>=num){
            if(babyv[mid].b==num)
                ans=babyv[mid].j;
            r=mid-1;
        }
        else l=mid+1;
    }
    return ans;
}
///B^x=N(modP)求解x,无解返回-1
long long babystep_giantstep(long long B,long long N,long long P)
{
    long long m=ceil(sqrt(P)),ans=1;
    for(long long j=0;j<m;j++)///预存操作
    {
        babyv[j].b=ans;
        babyv[j].j=j;
        ans=(ans*B)%P;///递推
    }
    ans=1;
    sort(babyv,babyv+m);///预存排序
    long long _Bm=q_pow(q_pow(B,P-2,P),m,P);///算出B^(-m)%P的值
    for(long long i=0;i<m;i++)
    {
        long long j=find(N*ans%P,m);///二分查找
        if(j!=-1)return i*m+j;///找到返回答案
        ans=(ans*_Bm)%P;///继续递推
    }
    return -1;///找不到答案
}

poj2417代码:点击打开链接

#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<utility>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Inf (1<<29)
#define LL long long
using namespace std;
const int MM=110;
const long long MOD=1000000007;
///大步小步算法
struct baby///小步算法预存的结构体定义
{
    long long b,j;
    bool operator < (const baby &other)const{
        return b<other.b;
    }
}babyv[100005];
///快速幂,x^y%mod
long long q_pow(long long x,long long y,long long mod)
{
    long long ans=1;
    while(y>0)
    {
        if(y&1)ans=(ans*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return ans;
}
///小步预存的个数为m的结构体里面查找num
long long find(long long num,long long m)
{
    long long l=0,r=m-1;
    while(r>=l)
    {
        long long mid=(r+l)/2;
        

这篇关于离散对数求解算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/977743

相关文章

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

Python绘制TSP、VRP问题求解结果图全过程

《Python绘制TSP、VRP问题求解结果图全过程》本文介绍用Python绘制TSP和VRP问题的静态与动态结果图,静态图展示路径,动态图通过matplotlib.animation模块实现动画效果... 目录一、静态图二、动态图总结【代码】python绘制TSP、VRP问题求解结果图(包含静态图与动态图

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.