• P3846 [TJOI2007] 可爱的质数/【模板】BSGS 题解


    原题链接

    简要题意:给定一个质数 \(p\),以及一个整数 \(a\),一个整数 \(n\),现在要求你计算一个最小的非负整数 \(x\),满足 \(a^x \equiv n \pmod p\).

    本题是 BSGS (BaBy Step Giant Step),即大步小步算法。

    下面我们将一步步引入该算法。考虑令 \(x = rt - s\),其中 \(s < t\),而 \(t\) 是我们给定的一个类似于 “块长” 的东西。

    \[\begin{aligned} & a^{rt - s} \equiv n \pmod p \\ & a^{rt} \equiv n \times a^s \pmod p \\ & (a^t)^r \equiv n \times a^s \pmod p \\ \end{aligned} \]

    注意到,这里我们可以用哈希进行处理。

    \(n \times a^s\) 的值最多有 \(t\) 个,因为 \(s < t\).

    \((a^t)^r\) 的值最多有 \(\lfloor \frac{p}{t} \rfloor\),因为 \(x \leq p\).

    哈希自带一个 \(\text{log}\),加上快速幂,于是该程序时间复杂度为 \(\mathcal{O}(t \log^2 t + \frac{p}{t} \log^2 \frac{p}{t})\).

    很显然,块长 \(t\) 在取到 \(\lfloor \sqrt{p} \rfloor\) 时时间复杂度最优。

    时间复杂度:\(\mathcal{O}(\sqrt{p} \log^2 \sqrt{p})\). 这在 \(p = 10 ^ {12}\) 的时候仍然是足以通过的。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    ll p,a,n;
    map<ll,ll> m;
    
    inline ll pw(ll x,ll y) {
    	ll ans=1; while(y) {
    		if(y&1) ans=ans*x%p;
    		x=x*x%p; y>>=1;
    	} return ans;
    }
    
    int main() {
    	scanf("%lld %lld %lld",&p,&a,&n);
    	ll t = sqrt(p);
    	for(ll s = 0 ; s < t ; s++) m[n * pw(a,s) % p] = s; // 计算式子右侧的值
    	a = pw(a,t);
    	ll ans = 1e17;
    	for(ll r = 1 ; r <= t; r++) 
    		if(m[pw(a,r)]) ans = min (ans , r * t - m[pw(a,r)]); // 寻找对应
    	printf(ans == 1e17 ? "no solution" : "%d",ans);
    	puts("");
    	return 0;
    }
    
    简易的代码胜过复杂的说教。
  • 相关阅读:
    基于C/S模式的程序更新下载
    拓展方法
    主从级GridView
    using 的用法
    五大数据类型
    redis的主从复制原理及步骤
    redis的发布订阅
    redis的持久化
    redis的事务
    配置文件详解
  • 原文地址:https://www.cnblogs.com/bifanwen/p/15725597.html
Copyright © 2020-2023  润新知