zoukankan      html  css  js  c++  java
  • BSGS&ExBSGS

    BSGS&ExBSGS

    求解形如

    [a^xequiv bpmod p ]

    的高次同余方程

    BSGS

    假装(gcd(a,p)=1)

    (m=lceilsqrt p ceil)

    然后把(x)分解成

    [x=i*m+j ]

    的形式。

    [a^xequiv bpmod p ]

    [a^{i*m+j}equiv bpmod p ]

    [a^{im}equiv b/a^jpmod p ]

    这时我们发现,(1≤j≤m-1),也就是说枚举(j)是非常简单的。

    这样我们就可以把(m-1)(j)全都存起来,存到哈希表中,然后枚举(i),这样就可以在(O(sqrt n + log (n)))的时间内求出解了。(分块 + map)

    (时间复杂度是wyh在网上找的,自己不会证qwq

    ExBSGS

    刚刚我们假装(gcd(a,p)=1),那要是没有这个条件怎么办呢?

    很简单,我们只要通过把两边同时除以 他们的 gcd 就好啦qwq

    (g=gcd(a,p)),如果(g ot| b),显然如果(p=1)(x=0),否则方程无解

    我们就得到

    [a^{x-1}*frac{a}{g}equiv frac{b}{g}pmod {frac{p}{g}} ]

    [a^{x-1}equiv frac{b}{a}pmod {frac{p}{g}} ]

    这样一直做下去,直到(g=1)为止。

    有一个误区(对于我这种蒟蒻)就是(a)(b/g)不一定互质。这是zzy学长告诉wyh的qwq,还是学长好啊qwq。

    好感动啊。。。

    Code

    
    typedef long long ll;
    map<ll,ll> ma;
    inline ll bsgs(ll a,ll b)//解a^x同余b (%mod) 
    {
    	a%=mod;b%=mod;
    	ma.clear();
    	ll m=ll(sqrt(mod+1)),e=1;
    	for(int j=0;j<m;++j)
    	{
    		if(!ma.count(e)) ma[e]=j;
    		e=e*a%mod;
    	}
    	if(gcd(e,mod)!=1) return -1;
    	ll inv=inverse(e);//逆元 
    	for(int i=0;i<m;++i)
    	{
    		if(ma.count(b)) return i*m+ma[b];
    		b=b*inv%mod;
    	}
    	return -1;
    }
    
    
  • 相关阅读:
    MySQL——SELECT
    启动 MySQL
    Ethernet and ARP 及Wireshark实验
    ICMP 协议及Wireshark实验
    Wireshark实验——IP 协议
    关键路径
    用树结构存储的图博客(笑)
    拓扑排序
    云计算部署的未来趋势将从自动化转向为自主化
    苹果拥抱 Rust,正在将 C 代码移植到 Rust
  • 原文地址:https://www.cnblogs.com/oierwyh/p/11375107.html
Copyright © 2011-2022 走看看