• bzoj2242: [SDOI2011]计算器 && BSGS 算法


    BSGS算法

    给定y、z、p,计算满足yx mod p=z的最小非负整数x。p为质数(没法写数学公式,以下内容用心去感受吧)

    x = i*m + j.

    y^(j)≡z∗y^(-i*m)) (mod p)

    y^(j)≡z∗ine(y^(i*m)) (mod p)(逆元)

    由费马小定理y^(p-1)≡1 (mod p) ine(y^m) = y^(p-m-1) 

    ine(y^(i*m)≡ine(y^((i−1)m))∗y^(p-m-1) 

    1.首先枚举同余符号左面,用一个hash保存(y^j,j),因为j可能等于0,所以hash[1]要赋为一个特殊值。

    2.再枚举同余符号右面,如果hash(z∗ine(y^(i*m)))存在,就找到了一组解。

    显然,m=sqrt(p)的时候复杂度最低为O(sqrt(p)),m=ceil(sqrt(p)).

    从这个人博客中可以看出,这个人对于BSGS算法有着相当深刻的理解,居然能够找到俩个有助于学习BSGS算法的俩首歌,还用了exgcd算法。

    http://www.cnblogs.com/yuiffy/p/3877381.html

    其他俩个操作为快速幂,exgcd。

    因为题目并不是一起写的,所以写了俩个快速幂。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<map>
    #include<cmath>
    using namespace std;
    
    int T,k;
    long long y,z,p;
    map<int,int> hash;
    
    long long q(long long z) {
        if(z==1) return y%p;
        long long m=q(z/2);
        if(z%2) return (((m*m)%p)*y)%p;
        return (m*m)%p;
    }
    
    void solve1() {
        printf("%lld
    ",q(z));    
    }
    
    long long exgcd(long long a,long long b,long long &x,long long &y) {
        if(b==0) {
            x=1; y=0;
            return a;
        }
        long long res=exgcd(b,a%b,y,x);
        y-=(a/b)*x;    
        return res;
    }
    
    void solve2(long long a,long long b,long long n) {
        long long x,y,ans,d,s;
        d=exgcd(a,n,x,y);
        if(b%d!=0) printf("Orz, I cannot find x!
    ");
        else {
            ans=(b/d)*x; s=n/d;
            ans=(ans%s+s)%s;
            printf("%lld
    ",ans);
        }
    }
    
    long long power(long long a,long long b,long long mod) {
        long long res=1;
        while(b) {
            if(b&1) res=res*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return res;
    }
    
    void solve3() {
        y%=p; z%=p;
        if(!y && !z) printf("1
    ");
        else if(!y) printf("Orz, I cannot find x!
    "); 
        else {
            long long m,v,e,res;
            m=ceil(sqrt(p)); v=power(y,p-m-1,p); e=1;    
            
            hash.clear();
            hash[1]=m+1;
            for(long long i=1;i<=m;i++) {
                e=e*y%p;
                if(!hash[e]) hash[e]=i;    
            }
            
            res=-1;
            for(long long i=0;i<m;i++) {
                if(hash[z]) {
                    res=i*m+(hash[z]==m+1?0:hash[z]);
                    break;            
                }
                z=z*v%p;            
            }
            if(res==-1) printf("Orz, I cannot find x!
    ");
            else printf("%d
    ",res);
        }
    }
    
    int main() {
        scanf("%d%d",&T,&k);
        while(T--) {
            scanf("%lld%lld%lld",&y,&z,&p);
            if(k==1) solve1();
            else if(k==2) solve2(y,z,p);
            else solve3();
        }
        return 0;
    }
  • 相关阅读:
    iOS开发日记1-tableview编辑
    nginx安装-del
    linux服务器su之后变成bash-4.1#
    PhoneGap & HTML5 学习资料网址
    PhoneGap通信机制的实现原理
    Android调用Java WebSevice篇之二
    Android调用Java WebSevice篇之一
    Java开发牛人十大必备网站
    百度地图生产工具
    PS制作圆角透明图片
  • 原文地址:https://www.cnblogs.com/invoid/p/5588857.html
Copyright © 2020-2023  润新知