zoukankan      html  css  js  c++  java
  • bsgs(Baby Steps Giant Steps)算法

    BSGS算法(Baby Steps Giant Steps算法,大步小步算法,北上广深算法,拔山盖世算法)

    适用问题

    对于式子:

    $$x^y=z(mod_p)$$

    已知x,z,p,p为质数;

    求解一个最小非负整数y;



    存在一个y,属于[0,p-2](费马小定理)

    于是有了一个笨拙的方法,枚举y

    枚举y,期望效率:O(P)

    寻求一种优化:

    对式子变型:

    设:$$y=isqrt{p}-j$$

    则$$x^{isqrt{p}-j}=z(mod_p)$$

    ——这个变型的用意在于把y拆开

    枚举y,变成枚举,i,j;

    i在1~$sqrt{p}$之间,j在0~$sqrt{p}$之间

    (根号上取整,其实i,j的范围大可大些——只要保证y不会小于0)

    枚举(i,j),期望效率:$O(sqrt{p}*sqrt{}p)$

    本质上没有优化

    接着变型:

    $$x^{isqrt{p}}=z*x^{j}(mod_p)$$ 

    ——这个变型的用意在于真正把y分离为两部分

    枚举j,把等号右边的模后得数置于hash_table,此时同一个得数只留最大的j值;

    从小到大枚举i,计算等号左边的模后得数,查询hash_table,第一个成功查询的i,与其相应的j,组成$isqrt{p}-j$即为最小的y,

    期望效率:$O(sqrt{p}*T(hash))$

    效率优异,拔山盖世的bsgs算法,就是这样了;



    例题:

    [SDOI2011]计算器

    代码:

    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    const int ss=999983; 
    using namespace std;
    int hash_tab[1000000],tot;
    struct ss{
        int nu,next,j;
    }data[1000000];
    void work();
    void work1();
    void work2();
    void work3();
    LL Sqr(LL ,int );
    int hash(int, int ,int );
    LL z,y,p;
    bool flag;
    int main()
    {
        work();
    }
    void work(){
        int T,K;
        scanf("%d%d",&T,&K);
        while(T--){
            scanf("%lld%lld%lld",&y,&z,&p);
            if(K==1)
                work1();
            if(K==2)
                work2();
            if(K==3)
                work3();
        }
    }
    void work1(){
        int i,j,k;
        printf("%lld
    ",Sqr(y,z));
    }
    void work2(){
        int ans,less;
        if((!(y%p)&&z)||((y%p)&&!z)){
            printf("Orz, I cannot find x!
    ");return;
        }
        printf("%lld
    ",Sqr(y%p,p-2)*z%p);
    }
    void work3(){
        long long ysqrtp,sqrtp=ceil(sqrt(p));
        memset(hash_tab,0,sizeof(hash_tab));
        memset(data,0,sizeof(data));
        long long l=1,r=z%p;
        int i,j;
        if((!(y%p)&&z)||((y%p)&&!z)){
            printf("Orz, I cannot find x!
    ");return;
        }
        ysqrtp=Sqr(y,sqrtp);
        for(i=0;i<=sqrtp;i++)
            hash(r,i,0),(r*=y)%=p;
        for(i=1;i<=sqrtp;i++){
            (l*=ysqrtp)%=p;
            if((j=hash(l,0,1))!=-1){
                printf("%lld
    ",i*sqrtp-j);
                return ;
            }
        }
        printf("Orz, I cannot find x!
    ");
    }
    LL Sqr(LL x,int n){
        LL ret=1;
        while(n){
            if(n&1)(ret*=x)%=p;
            (x*=x)%=p;n>>=1;
        }
        return ret;
    }
    int hash(int num,int j,int flag){
        int tem;
        for(tem=hash_tab[num%ss];tem;tem=data[tem].next){
            if(data[tem].nu==num){
                if(!flag&&j>data[tem].j)
                    data[tem].j=j;
                return data[tem].j;
            }
            if(!data[tem].next&&!flag){
                data[tem].next=++tot;
                data[tot].j=j;
                data[tot].nu=num;
                return -1;
            }
        }
        if(!flag){
            hash_tab[num%ss]=++tot;
            data[tot].j=j;
            data[tot].nu=num;
        }
        return -1;
    }
    View Code
  • 相关阅读:
    明就要发布一加8pro了,发几张关于7的图片供大家回忆下
    【移动端开发】移动端开发项目架构
    【前端开发】three.js入门
    【前端依赖】live-server静态文件本热更新静态服务安装及使用教程
    【vue开发】泛型总结
    【vue前端开发】微信扫码登录
    【正则表达式】梳理
    【mock数据服务】大项目中mock的使用方法和注意事项
    【vue开发】v-bind="$attrs" v-on="$listeners" 多层组件监听
    【vue开发】render的用法,全局引入/组件简化代码
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/7493671.html
Copyright © 2011-2022 走看看