zoukankan      html  css  js  c++  java
  • BSGS

    前言

    B(拔)S(山)G(盖)S(世) ,即 Baby Step Giant Step ,大步小步算法。

    用于解高次同余方程,形如 \(y^x\equiv z\pmod p\) ,求 x 的最小非负整数解

    普通 BSGS

    • \(\gcd(y,p)=1\) 时,可以使用本算法

    • 将 x 表示为 \(am-b,m=\sqrt{p},b<m\) ,那么原式变为 \(y^{am}\equiv zy^b\pmod p\)

    • 枚举 b 的所有值,把右边的值用哈希或 map 存起来

    • 对于左边,枚举 a ,查询右边是否有相等即可

    • 时间复杂度 \(O(\sqrt{p})\)

    模板

    1. SDOI 2011 计算器
      • 操作一:快速幂
      • 操作二:exgcd
      • 操作三:普通 bsgs
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    inline LL Pow(LL x,LL y,LL p) {
    	register LL res=1;
    	for(;y;y>>=1,x=(x*x)%p)
    	if(y&1)res=(res*x)%p;
    	return res;
    }
    LL exgcd(LL p,LL q,LL &x,LL &y) {
    	if(!q)return x=1,y=0,p;
    	register LL gcd=exgcd(q,p%q,y,x);
    	return y-=p/q*x,gcd;
    }
    const int Su=100007;
    struct HASH {
    	int cnt,lst[Su],nxt[Su],id[Su]; LL vl[Su];
    	inline void Clear() { memset(lst,0,sizeof(lst)),cnt=0; }
    	inline void Ins(LL x,int p) {
    		vl[++cnt]=x,id[cnt]=p,x%=Su;
    		nxt[cnt]=lst[x],lst[x]=cnt;
    	}
    	inline int Find(LL x) {
    		for(int i=lst[x%Su];i;i=nxt[i])
    			if(vl[i]==x)return id[i];
    		return -1;
    	}
    }hs;
    inline LL BSGS(LL x,LL y,LL p) {
    	if(x%p==0)return -1;
    	x%=p,y%=p;
    	if(y==1)return 0;
    	register int z=sqrt(p)+1;
    	register LL sx=y,sy;
    	hs.Clear();
    	for(register int i=0;i<z;++i,sx=sx*x%p)
    		hs.Ins(sx,i);
    	sy=Pow(x,z,p),sx=1;
    	for(register int i=1,k;i<=z;++i) {
    		sx=sx*sy%p,k=hs.Find(sx);
    		if(k!=-1)return 1LL*i*z-1LL*k;
    	}
    	return -1;
    }
    int T,K;
    int main() {
    	scanf("%d%d",&T,&K);
    	for(LL x,y,p,tmp,u,v;T--;) {
    		scanf("%lld%lld%lld",&x,&y,&p);
    		if(K==1)printf("%lld\n",Pow(x,y,p));
    		else if(K==2) {
    			tmp=exgcd(x,p,u,v);
    			if(y%tmp)puts("Orz, I cannot find x!");
    			else u*=y/tmp,v=p/tmp,printf("%lld\n",(u%v+v)%v);
    		} else {
    			tmp=BSGS(x%p,y%p,p);
    			if(tmp<0)puts("Orz, I cannot find x!");
    			else printf("%lld\n",tmp);
    		}
    	}
    }
    

    EX BSGS

    • \(\gcd(y,p)\ne 1\) 时使用本算法,设 \(d=\gcd(y,p)\)
    • 把原式写为 \(y*y^{x-1}+k*p=z,k\in\mathbb{Z}\) 的形式,根据裴蜀定理 ,若 d 不是 z 的约数就无解
    • 那么 \(\dfrac{y}{d}y^{x-1}+k*\dfrac{p}{d}=\dfrac{z}{d},d=\gcd(\dfrac{z}{d},y)\) ,一直做到 \(d=1\)
    • 设 d 的乘积为 g ,做了 c 次
    • \(x'=x-c,p'=\dfrac{p}{g},z'=\dfrac{z}{g}\)
    • 那么 \(y^{x'}*\dfrac{y^c}{g}\equiv z'\pmod{p'}\)
    • 用普通 BSGS 求解即可

    模板

    SPOJ Power Modulo Inverted

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    inline LL Pow(LL x,LL y,LL p) {
    	register LL res=1;
    	for(;y;y>>=1,x=x*x%p)
    	if(y&1)res=res*x%p;
    	return res;
    }
    inline LL Gcd(LL p,LL q) { return q?Gcd(q,p%q):p; }
    const int Su=100007;
    struct HASH {
    	int cnt,nxt[Su],lst[Su],id[Su]; LL vl[Su];
    	inline void Clear() { memset(lst,0,sizeof(lst)),cnt=0; }
    	inline void Ins(LL x,int p) {
    		vl[++cnt]=x,id[cnt]=p,x%=Su;
    		nxt[cnt]=lst[x],lst[x]=cnt;
    	}
    	inline int Find(LL x) {
    		for(int i=lst[x%Su];i;i=nxt[i])
    			if(vl[i]==x)return id[i];
    		return -1;
    	}
    }hs;
    LL x,y,p,ans;
    inline LL EX_BSGS() {
    	x%=p,y%=p;
    	if(y==1)return 0;
    	register LL cnt=0,k=1;
    	for(LL d=Gcd(x,p);d>1;d=Gcd(x,p)) {
    		if(y%d)return -1;
    		y/=d,p/=d,++cnt,k=k*x/d%p;
    		if(k==y)return cnt;
    	}
    	hs.Clear();
    	register int z=sqrt(p)+1;
    	register LL sx=y,sy;
    	for(int i=0;i<z;i++,sx=sx*x%p)
    		hs.Ins(sx,i);
    	sy=Pow(x,z,p),sx=k;
    	for(int i=1,o;i<=z;i++) {
    		sx=sx*sy%p,o=hs.Find(sx);
    		if(o!=-1)return i*z-o+cnt;
    	}
    	return -1;
    }
    int main() {
    	scanf("%lld%lld%lld",&x,&p,&y);
    	for(;x|y|p;) {
    		ans=EX_BSGS();
    		if(ans<0)puts("No Solution");
    		else printf("%lld\n",ans);
    		scanf("%lld%lld%lld",&x,&p,&y);
    	}
    }
    
  • 相关阅读:
    arrayObj.splice(start, deleteCount, [item1[, item2[, . . . [,itemN]]]])
    运算符 ||
    ajax 本地测试,使用Chrome 浏览器
    js set
    js get 传参 汉字 乱码问题
    删除对象中的key
    html 返回页面顶部
    js 设置回车事件
    盘面,盘口
    ST股
  • 原文地址:https://www.cnblogs.com/KonjakLAF/p/14396937.html
Copyright © 2011-2022 走看看