zoukankan      html  css  js  c++  java
  • BSGS算法

    BSGS算法

    我是看着(ppl)的博客学的,您可以先访问(ppl)的博客

    Part1 BSGS算法

    求解关于(x)的方程

    [y^x=z(mod p) ]

    其中((y,p)=1)
    做法并不难,我们把(x)写成一个(am-b)的形式
    那么,原式变成了
    (y^{am}=zy^b(mod p))
    我们求出所有(b)可能的取值(0~m-1),并且计算右边的值
    同时用哈希或者(map)之类的东西存起来,方便查询
    对于左边,我们可以枚举所有可能的(a),然后直接查右边的值有没有相等的即可
    复杂度是(O(max(m,p/m)))
    不难证明(m=sqrt(p))时复杂度最优

    所以(bsgs)算法的复杂度是(O(sqrt(p)))

    模板题:(SDOI2011) 计算器

    关键代码:

    int m=sqrt(p)+1;Hash.Clear();
    for(RG int i=0,t=z;i<m;++i,t=1ll*t*y%p)Hash.Insert(t,i);
    for(RG int i=1,tt=fpow(y,m,p),t=tt;i<=m+1;++i,t=1ll*t*tt%p)
    {
    	int k=Hash.Query(t);if(k==-1)continue;
    	printf("%d
    ",i*m-k);return;
    }
    

    使用(map)会多个(log),在洛谷上我写的(Hash)目前是跑得最快的。。。

    Part2 拓展BSGS

    假设(gcd(y,p) eq 1)怎么办?
    (d=gcd(y,p))
    将方程改写成等式形式

    [y^x+kp=z ]

    发现此时的(z)必须要是(d)的倍数,否则无解。
    因此,除掉(d)

    [frac{y}{d}y^{x-1}+kfrac{p}{d}=frac{z}{d} ]

    这样前面的(y/d)就是一个系数了,
    不断检查(gcd(frac{z}{d},y)),一直除到互质为止
    此时的形式就变成了

    [frac{y^k}{d}y^{x-k}=frac{z}{d}(mod frac{p}{d}) ]

    这样子(bsgs)求解之后在还原回去就行了。

    模板:SPOJ Power Modulo Inverted
    关键代码

    void ex_BSGS(int y,int z,int p)
    {
    	if(z==1){puts("0");return;}
    	int k=0,a=1;
    	while(233)
    	{
    		int d=__gcd(y,p);if(d==1)break;
    		if(z%d){NoAnswer();return;}
    		z/=d;p/=d;++k;a=1ll*a*y/d%p;
    		if(z==a){printf("%d
    ",k);return;}
    	}
    	Hash.clear();
    	int m=sqrt(p)+1;
    	for(int i=0,t=z;i<m;++i,t=1ll*t*y%p)Hash.Insert(t,i);
    	for(int i=1,tt=fpow(y,m,p),t=1ll*a*tt%p;i<=m;++i,t=1ll*t*tt%p)
    	{
    		int B=Hash.Query(t);if(B==-1)continue;
    		printf("%d
    ",i*m-B+k);return;
    	}
    	NoAnswer();
    }
    
  • 相关阅读:
    卷积:如何成为一个很厉害的神经网络
    卷积的本质及物理意义(全面理解卷积)
    傅里叶分析之掐死教程(完整版)
    buf.writeUInt16BE()
    buf.writeUInt8()函数详解
    buf.writeUIntBE()函数详解
    buf.writeInt32BE()函数详解
    buf.writeInt16BE()函数详解
    buf.writeInt8()函数详解
    buf.writeDoubleBE()函数详解
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8810050.html
Copyright © 2011-2022 走看看