BSGS(扩展篇,思路+详解)

扩展篇

问题:

当 p , a p,a p,a可能不互质时,求
a x ≡ b ( m o d   p ) a^x\equiv b(mod~p)\\ ax≡b(mod p)

方法:

当 d 1 = g c d ( a , p ) ≠ 1 d_1=gcd(a,p)\neq1 d1​=gcd(a,p)​=1,当 d 1 ∤ b d_1\nmid b d1​∤b时,无解,则原式变成:
a d 1 a x − 1 ≡ b d 1 ( m o d   p d 1 ) \frac a{d_1}a^{x-1}\equiv \frac b{d_1}(mod~\frac p{d_1})\\ d1​a​ax−1≡d1​b​(mod d1​p​)
当设 d 2 = g c d ( a , p d 1 ) ≠ 1 d_2=gcd(a,\frac p{d_1})\neq1 d2​=gcd(a,d1​p​)​=1,当 d 2 ∤ b d 1 d_2\nmid \frac b{d_1} d2​∤d1​b​时,无解,则原式可变成:
a 2 d 1 d 2 a x − 2 ≡ b d 1 d 2 ( m o d   p d 1 d 2 ) \frac {a^2}{d_1d_2}a^{x-2}\equiv \frac b{d_1d_2}(mod~\frac p{d_1d_2})\\ d1​d2​a2​ax−2≡d1​d2​b​(mod d1​d2​p​)
重复直到 d c n t = 1 d_{cnt}=1 dcnt​=1。设 D = ∏ i = 1 c n t d i D=\prod_{i=1}^{cnt}d_i D=∏i=1cnt​di​,原式可以写成:
a c n t D a x − c n t ≡ b D ( m o d   p D ) \frac {a^{cnt}}Da^{x-cnt}\equiv \frac bD(mod~\frac pD)\\ Dacnt​ax−cnt≡Db​(mod Dp​)
剩下的 a x − c n t , b D , p D a^{x-cnt},\frac bD,\frac pD ax−cnt,Db​,Dp​,可以构成基础篇的 b s g s bsgs bsgs,修改的地方就是乘了一个系数 a c n t D \frac {a^{cnt}}D Dacnt​。

注意: c n t cnt cnt可能大于x这个解,所以我们在做除法的时候就要判断是不是能够相等,相等直接输出当前的 c n t cnt cnt。

题目:

P4195 【模板】扩展BSGS

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll x, ll y, ll mod) {
    ll ans = 1;
    while(y) {
        if(y & 1) ans = ans * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return ans;
}
unordered_map<ll, ll> mp;
ll bsgs(ll a, ll b, ll p, ll ad) {
    if(a % p == 0 && b%p != 0) return -1;
    mp.clear();
    int k = ceil(sqrt(p));
    for(int i=0; i<k; i++) {
        mp[b] = i;
        b = b * a % p;
    }
    ll aa = qpow(a, k, p), A = aa*ad % p;
    for(int i=1; i<=k; i++) {
        if(mp[A]) return 1ll*i*k - mp[A];
        A = A * aa % p;
    }
    return -1;
}
ll exgcd(ll &x, ll &y, ll a, ll b) {
    if(b == 0) {
        x = 1, y = 0;
        return a;
    }
    ll d = exgcd(x, y, b, a%b);
    ll tmp = y;
    y = x - a/b * y;
    x = tmp;
    return d;
}
ll inv(ll a, ll b) {
    ll x, y;
    ll d = exgcd(x, y, a, b);
    return x;
}

ll exbsgs(ll a, ll b, ll p) {
    a %= p, b %= p;
    if(b == 1 || p == 1) return 0;
    ll cnt = 0, d, tmp = 1;
    while((d = __gcd(a, p)) ^ 1) {
        if(b % d) return -1;
        cnt++, b /= d, p /= d;
        tmp = tmp * a/d % p;
        if(tmp == b) return cnt;
    }
    ll ans = bsgs(a, b, p, tmp);
    if(ans == -1) return -1;
    else return ans + cnt;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    ll a, p, b, d;
    while(cin >> a >> p >> b) {
        if(!a || !p || !b) break;
        ll ans = exbsgs(a, b, p);
        if(ans != -1) cout << ans << endl;
        else cout << "No Solution\n";
    }
    return 0;
}
上一篇:net 后台任意设置 控件显示和隐藏就OK


下一篇:Windows 2016 无域故障转移群集部署方法 超详细图文教程