BSGS

BSGS

做起来超级休闲的
求解\(a^x \equiv b (\mod p)\)
复杂度是\(\sqrt p\)
首先考虑,如何暴力
直接暴力枚举\(<p\)的指数
\(a^{p-1} \equiv 1(\mod p)\)
那么就是一个循环节了.
考虑如何在\(\sqrt p\)时间内解决这个问题.
指数\(x\)可以拆成\(k * t - m(t = \sqrt{p}), 0<=m<=t,1<=k<=\frac pt\)
\(a^{k*t - m} \equiv b(\mod p)\)
\(\frac {a^{k*t}}{a^m }\equiv b(\mod p)\)
\(a^{k*t}\equiv b * a^m(\mod p)\)
\(a^{k*t}b'\equiv a^m(\mod p)\)
\(b'\)\(b\)的逆元.
其实把b放后面也可以啦,我可能是ZZ了.>>_<<
然后直接暴力枚举\(k\),用hash存下\(a^m\)的值,然后就可以\(O(\sqrt p)\)做了
附上代码 (SDOI2011 计算器)

/*gzy is a big B*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#define rep(i , x, p) for(int i = x;i <= p;++ i)
#define sep(i , x, p) for(int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
#define ll long long
using std::min;
using std::max;
using std::swap;
using std::__gcd;
#define int long long

inline int gi() {int x = 0,f = 1;char c = gc;while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;}
void print(ll x) {if(x < 0) pc('-') , x = -x;if(x >= 10) print(x / 10);pc(x % 10 + '0');}

void Sub1(int a , int b , int mod) {
    int ans = 1;
    for(int now = a;b;b >>= 1,now = now * now % mod) 
        if(b & 1) ans = ans * now % mod;
    print(ans);pc('\n');
}

int exgcd(int a , int b,int &x,int &y) {
    if(!b) {
        x = 1;y = 0;
        return a;
    }
    int g = exgcd(b ,a % b,x , y);
    int tmp = x;
    x = y;
    y = tmp - a / b * y;
    return g;
}

void Sub2(int a,int z,int p) {
    int x , y;
    int g = exgcd(a , p,x , y);
    if(z % g) {puts("Orz, I cannot find x!");return;}
    p /= g;
    x = x * z / g;
    x = x % p + p;
    x = x % p;
    print(x);pc('\n');
    return;
}
std::map<int , int> mp;

int fp(int a , int b, int mod) {
    int ans = 1;
    for(int now = a;b;b >>= 1 , now = now * now % mod)
        if(b & 1) ans = ans * now % mod;
    return ans;
}
int mul(int x, int y,int p) {return 1ll * x * y % p;}

int BSGS(int a , int b , int p) {
    int M = ceil(sqrt(p)) , base = fp(a , M , p) , g = __gcd(a , p);if(g != 1) return -1;
    mp.clear();
    for(int i = 0 , now = b;i <= M;++ i) {
        mp[now] = i + 1;
        now = now * a % p;
    }
    for(int i = 1 , now = base;i <= M;++ i) {
        if(mp[now]) return i * M - mp[now] + 1;
        now = now * base % p;
    }
    return -1;
}

void Sub3(int a , int b , int c) {
    b %= c;
    int ans = BSGS(a , b, c);
    ans == -1 ? puts("Orz, I cannot find x!") : (print(ans) , pc('\n'));
    return;
}

main() {
//  freopen("1.in","r",stdin);
    int T = gi() , opt = gi();
    while(T --) {
        int a = gi() , b = gi(), c = gi();
        if(opt == 1) Sub1(a , b, c);
        else if(opt == 2) Sub2(a , b, c);
        else Sub3(a , b, c);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gzygzy/p/10188495.html