• BSGS及扩展BSGS总结(BSGS,map)


    蒟蒻哪里有什么总结,只能点击%YL%

    还有这位ZigZagK大佬的blog

    (mbox{BSGS})

    模板题:洛谷P3846 [TJOI2007]可爱的质数

    给定(a,b)和模数(mbox{YL}),求(a^xequiv b(modmbox{YL}))(x)的最小非负整数解。保证(gcd(a,mbox{YL})=1)

    (k=lceilsqrt{mbox{YL}} ceil),令(x=ky-c)(yin[1,k],cin[0,k)),故分解唯一)

    于是有(a^{ky}equiv ba^c(modmbox{YL}))

    两边的取值都只有(k)种,枚举右边丢进map,再枚举左边查找一下即可得到最小的解。

    复杂度(O(sqrt{mbox{YL}}logsqrt{mbox{YL}}))。注意特判掉一些特殊情况。

    #include<bits/stdc++.h>
    #define LL long long
    #define RG register
    #define R RG int
    using namespace std;
    map<int,int>c;
    inline LL qpow(RG LL b,R k,RG LL YL){//快速幂
    	RG LL a=1;
    	for(;k;k>>=1,b=b*b%YL)
    		if(k&1)a=a*b%YL;
    	return a;
    }
    int main(){
    	R a,b,YL;
    	cin>>YL>>a>>b;
    	if((b%=YL)==1)return puts("0"),0;//特判×2
    	if((a%=YL)==0)return puts("no solution"),0;
    	R k=sqrt(YL)+1,y;
    	RG LL p,pw=qpow(a,k,YL);
    	for(p=b,y=0;y<k;++y,(p*=a)%=YL)//预处理
    		c[(int)p]=y;
    	for(p=pw,y=1;y<=k;++y,(p*=pw)%=YL)//查找
    		if(c.count((int)p))return(cout<<(LL)k*y-c[(int)p]<<endl),0;
    	return puts("no solution"),0;//找不到
    }
    

    扩展(mbox{BSGS})

    模板题:洛谷P4195 Spoj3105 Mod
    双倍经验:洛谷SP3105 MOD - Power Modulo Inverted

    可以解决(gcd(a,mbox{YL}) eq1)的情况,核心思想是试探性地约去(gcd)

    同余方程(a^xequiv b(modmbox{YL})),可以提一个(a)出来改成不定方程(acdot a^{x-1}+mbox{YL}cdot y=b),等于说暂时把(a^{x-1})看成了未知数。

    (g=gcd(a,mbox{YL})),学完exgcd之后我们就知道了如果(g mid b)则方程组无解。否则就可以约成(frac a gcdot a^{x-1}+frac{mbox{YL}}gcdot y=frac b g)

    我们把约简后的方程看作一个新的不定方程(a'cdot a^{x-1}+mbox{YL}'cdot y=b'),如果(gcd(a,mbox{YL}'))还是不为(1)的话,我们就再从幂里面拿出一个(a)(mbox{YL}')约。如此循环。

    终于在约了(cnt)次后,我们得到了一个(gcd=1)的方程了,变回来就是(a'cdot a^{x-cnt}equiv b'(modmbox{YL}'))

    接下来的解法已经属于常规(mbox{BSGS})了,不过因为一些细节上的区别还是再写一遍。

    仍然设(k=lceilsqrt{mbox{YL}'} ceil),令(x=ky-c)(yin[1,k],cin[0,k))

    于是有(a'cdot a^{ky}equiv ba^{cnt}cdot a^c(modmbox{YL}')),其实只是恒等号两边多乘了点东西而已。

    约分多出来的复杂度是(O(log^2mbox{YL})),因为最多被约(log)次,它的阶小于根号就忽略掉了。又要注意一些特判。

    #include<bits/stdc++.h>
    #define LL long long
    #define RG register
    #define R RG int
    using namespace std;
    map<int,int>c;
    inline LL qpow(RG LL b,R k,RG LL YL){
        RG LL a=1;
        for(;k;k>>=1,b=b*b%YL)
            if(k&1)a=a*b%YL;
        return a;
    }
    int gcd(R x,R y){
        return y?gcd(y,x%y):x;
    }
    int main(){
        R a,b;RG LL YL;
        cin>>a>>YL>>b;
        while(a||b||YL){
            R x=-1,a1=1,cnt=0,g,k,y,p,pw;
            a%=YL;
            if((b%=YL)==1){x=0;goto L;}//这个特判上面提过
            while((g=gcd(a,YL))!=1){
                if(b%g)goto L;//无解充要条件
                ++cnt;b/=g;YL/=g;
                a1=a/g*(LL)a1%YL;
                if(a1==b){x=cnt;goto L;}
            }//注意这个特判,此时等价于a^{x-cnt}≡1(mod YL)
            c.clear();//多组数据注意清空
            k=sqrt(YL)+1;//常规BSGS过程
            pw=qpow(a,k,YL);
            p=b*qpow(a,cnt,YL)%YL;
            for(y=0;y<k;++y,p=(LL)p*a%YL)
                c[p]=y;
            p=(LL)a1*pw%YL;//多乘一个a1
            for(y=1;y<=k;++y,p=(LL)p*pw%YL)
                if(c.count(p)){x=k*y-c[p];break;}
          L:~x?printf("%d
    ",x):puts("No Solution");
            cin>>a>>YL>>b;
        }
        return 0;
    }
    
  • 相关阅读:
    JAVA调用WCF
    写代码之前要做什么?
    漫谈界面和数据
    UIButton 简易的UI
    数据结构利器之私房STL(中)
    有趣的位运算
    基于TCP的C/S初级网络编程1
    数据结构利器之私房STL(上)
    Unix/Linux 那些系统启动后的进程
    【字符串匹配】KMP算法之道
  • 原文地址:https://www.cnblogs.com/flashhu/p/9737769.html
Copyright © 2020-2023  润新知