BSGS&EXBSGS 大手拉小手,大步小步走

BSGS代码:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=46349;
const int mod=100003;
ll p,A,B;
ll ni[N];
struct node{
    int nxt[mod],val[mod],id[mod],cnt;
    int hd[mod];
    void init(){
        memset(nxt,0,sizeof nxt),memset(val,0,sizeof val);cnt=0;
        memset(hd,0,sizeof hd);memset(id,0,sizeof id);
    }
    void insert(ll x,int d){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return;
        }
        val[++cnt]=x;nxt[cnt]=hd[st];id[cnt]=d;hd[st]=cnt;
    }
    int find(ll x){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return id[i];
        }
        return -233;
    }
}ha;
map<ll,int>mp;
ll qm(ll a,ll b){
    ll ret=1,base=a;
    while(b){
        if(b&1) ret=(ret*base)%p;
        base=(base*base)%p;
        b>>=1;
    }
    return ret;
}
ll BSGS(){
    ll up=(ll)floor(sqrt(1.0*p-1))+1;
    cout<<up<<endl;
    ni[0]=1;
    for(int i=1;i<=up;i++){
        ni[i]=qm(qm(A,i*up),p-2);
    }
    for(int i=0;i<up;i++){
        ll t=qm(A,i);
        ha.insert(t,i);
    }
    for(int i=0;i<=up;i++){
        if(i*up>p-1) break;
        ll ri=B*ni[i]%p;
        ll ret=ha.find(ri);
        if(ret>=0) return i*up+ret;
    }
    return -233;
}
int main()
{
    while(scanf("%lld",&p)!=EOF){
        scanf("%lld%lld",&A,&B);
        ha.init();
        ll ret=BSGS();
        if(ret==-233){
            puts("no solution");
        }
        else{
            printf("%lld\n",ret);
        }
    }
    return 0;
}

BSGS

EXBSGS代码:poj3243

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=31630;//sqrt fai()
const int mod=100003;
ll C,A,B;
ll ni[N];
struct node{
    int nxt[mod],val[mod],id[mod],cnt;
    int hd[mod];
    void init(){
        memset(nxt,0,sizeof nxt),memset(val,0,sizeof val),memset(id,0,sizeof id);
        memset(hd,0,sizeof hd),cnt=0;
    }
    void insert(ll x,int d){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return;
        }
        val[++cnt]=x,nxt[cnt]=hd[st],id[cnt]=d,hd[st]=cnt;
    }
    int find(ll x){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return id[i];
        }
        return -233;
    }
}ha;
int pr[N],ci[N];
int tot;
ll kuai(ll a,ll b){
    ll ret=1,base=a;
    while(b){
        if(b&1) ret=(base*ret);
        base=base*base;
        b>>=1;
    }
    return ret;
}
ll fai(ll x){
    memset(ci,0,sizeof ci);tot=0;
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            pr[++tot]=i;
            while(x%i==0){
                ci[tot]++;
                x/=i;
            }
        }
    }
    if(x!=1) pr[++tot]=x,ci[tot]=1;
    ll ret=1;
    for(int i=1;i<=tot;i++){
        ll nn=kuai(pr[i],(ci[i]-1));
        ret*=nn*(pr[i]-1);
    }
    return ret;
}
ll qm(ll a,ll b,ll p){
    ll ret=1,base=a;
    while(b){
        if(b&1) ret=(base*ret)%p;
        base=(base*base)%p;
        b>>=1;
    }
    return ret;
}
int gcd(int a,int b){
    return (b==0)?a:gcd(b,a%b);
}
int BSGS(ll a,ll b,ll c){
    //cout<<a<<" "<<b<<" "<<c<<endl;
    int up=(int)floor(sqrt(1.0*c-1))+1;
    ni[0]=1;
    int mi=fai(c);
    //cout<<"oula "<<mi<<endl;
    for(int i=1;i<=up;i++){
        ni[i]=qm(qm(a,i*up,c),mi-1,c);
    }
    for(int i=0;i<=up-1;i++){
        ll kk=qm(a,i,c);
        ha.insert(kk,i);
    }
    for(int i=0;i<=up;i++){
        ll bb=b*ni[i]%c;
        int kk=ha.find(bb);
        if(kk>=0) return i*up+kk;
    }
    return -233;
}
int EXBSGS(){
    int num=0;
    int yC=C;
    int yB=B;
    int yA=A;
    ll ji=1;
    int ret=-233;
     bool flag=false;
    while(1){
        int g=gcd(A,C);
        //cout<<"gg "<<g<<endl;
        if(g==1) break;
        if(B%g) {
            flag=true;break;
        }
        B/=g,C/=g,ji=(ji*A/g)%C;
        num++;
    }
//    cout<<A<<" "<<B<<" "<<C<<endl;
    //cout<<" num "<<num<<endl;
    for(int i=0;i<=num;i++){
        ll kk=qm(yA,i,yC);
        //cout<<" kk "<<kk<<endl;
        if(kk%yC==yB) return i;
    }
    if(!flag){
        ll ni=1;
        ll mi=fai(C);
        ni=qm(ji,mi-1,C);
        ll NB=(B*ni)%C;
        ret=BSGS(A,NB,C);
    }
    if(ret>=0) return ret+num;
    else return -233;
}
int main(){
    while(1){
        scanf("%lld%lld%lld",&A,&C,&B);
        if(A==0&&B==0&&C==0) break;
        ha.init();
        B%=C;
        int ret=EXBSGS();
        if(ret>=0){
            printf("%d\n",ret);
        }
        else{
            puts("No Solution");
        }
    }
    return 0;
}

EXBSGS

原文地址:https://www.cnblogs.com/Miracevin/p/9261234.html

时间: 2024-10-06 11:22:31

BSGS&EXBSGS 大手拉小手,大步小步走的相关文章

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

js之图片变大变小效果

1.当鼠标移到图片上,图片变大:当鼠标移出图片,图片变小,效果如图: 2.原理不难,就是鼠标over时,设置一个定时器,让图片逐渐变大,鼠标out时同理,看下最初的简略代码你就会明白: <!DOCTYPE html> <html> <head> <style type="text/css"> div {     width: 200px;           /* 宽度 */     height: 100px;          /* 

分享《自然语言处理理论与实战》PDF及代码+唐聃+《深入浅出Python机器学习》PDF及代码+段小手+《深度学习实践:计算机视觉》PDF+缪鹏+《最优化理论与算法第2版》高清PDF+习题解答PDF+《推荐系统与深度学习》PDF及代码学习

<自然语言处理理论与实战>高清PDF,362页,带书签目录,文字可以复制:配套源代码.唐聃等著. <大数据智能互联网时代的机器学习和自然语言处理技术>PDF,293页,带书签目录,文字可以复制,彩色配图.刘知远等著.  下载: https://pan.baidu.com/s/1waP6C086-32_Lv0Du3BbNw 提取码: 1ctr <自然语言处理理论与实战>讲述自然语言处理相关学科知识和理论基础,并介绍使用这些知识的应用和工具,以及如何在实际环境中使用它们.由

《深入浅出Python机器学习(段小手)》PDF代码+《推荐系统与深度学习》PDF及代码+《自然语言处理理论与实战(唐聃)》PDF代码源程序

<深入浅出Python机器学习>PDF,280页,带书签目录,文字可以复制:配套源代码. 作者:段小手 下载: https://pan.baidu.com/s/1XUs-94n0qKR1F9rS8KNLHw 提取码: dv74 <深入浅出Python机器学习>内容涵盖了有监督学习.无监督学习.模型优化.自然语言处理等机器学习领域所必须掌握的知识,从内容结构上非常注重知识的实用性和可操作性. <深入浅出Python机器学习>采用由浅入深.循序渐进的讲授方式,完全遵循和尊重

delphi Form属性设置 设置可实现窗体无最大化,并且不能拖大拖小

以下设置可实现窗体无最大化,并且不能拖大拖小BorderIcon 设为---biMax[False] biHelp [False]BorderStyle 设为---bsSingle 参考-------------- 可以通过设置窗体的属性以及编程的方法,限制和控制窗体的变化.如让窗体不能最小化.最大化.-----1.通过属性设置方法使用Form的BorderIcon属性,我们可设置窗体是否具有系统菜单(biSystemMenu).最小化按钮(biMinimize).最大化按钮(biMaximiz

输入6个人的成绩放入到一个一维数组中,然后打印出平均分,最后按成绩 从大到小打印。三个功能(输入是一个函数,求平均分是一个函数,排序是一个 函数)都用函数实现,最后在main方法中调用。

/*5.输入6个人的成绩放入到一个一维数组中,然后打印出平均分,最后按成绩从大到小打印.三个功能(输入是一个函数,求平均分是一个函数,排序是一个函数)都用函数实现,最后在main方法中调用.*/ #include <stdio.h> int inputScore(){ int score; scanf("%d",&score); return score;} double avg(int scores[],int length){ int i,score = 0;

由多个电容组成的去耦旁路电路,电容怎么布局摆放,先大后小还是先小后大?

由多个电容组成的去耦旁路电路,电容怎么布局摆放,先大后小还是先小后大? PCB设计规范与指南, 电磁兼容 EMC, 高频高速PCB设计 by xfire 去耦旁路电磁兼容高速电路设计 对于噪声敏感的IC电路,为了达到更好的滤波效果,通常会选择使用多个不同容值的电容并联方式,以实现更宽的滤波频率,如在IC电源输入端用1μF.100nF和10nF并联可以实现更好的滤波效果.那现在问题来了,这几个不同规格的电容在PCB布局时该怎么摆,电源路径是先经大电容然后到小电容再进入IC,还是先经过小电容再经过大

2016.06.06 周一 C语言 将字符串根据字符的ASCII码从大到小排序并打印出字符串中的字符类型的总数

第一次变量冲突问题 解决了一个多小时,.... 代码如下: ↓ #include<stdio.h> #include<string.h> #define N 200 //输入字符串的最大长度 int main() { //************************输入开始部分******************************** printf("请输入字符串.(长度在200以内)\n\n"); int i=0,j,k,temp,lowLetter