计算器——大步小步算法(BSGS)

目录

一.什么是大步小步算法(BSGS)

二.模板

三.进阶例题:计算机

1.题目

2.题解

3.代码

谢谢!


一.什么是大步小步算法(BSGS)

a^{x}\equiv b(mod p)已知a,b,p,求x。

形如这样的同余式问题,可以用大步小步算法解决:(a^{\sqrt{p}})^{k}\equiv b*a^{m}(modp)(k\leq \sqrt{p},m\leq \sqrt{p})直接将所有(a^{\sqrt{p}})^{k}存入map,再用b*a^{m}来对拍,找到合法的m和k,最后x=k\sqrt{p}-m

证明:

x=k\sqrt{p}-m,那么原式可变为a^{k\sqrt{p}-m}\equiv b(mod p)

又可变为a^{k\sqrt{p}}/a^{m}\equiv b(mod p)

a^{k\sqrt{p}}\equiv b*a^{m}(modp)

(a^{\sqrt{p}})^{k}\equiv b*a^{m}(modp)

二.模板

出自一道模板题:

Discrete Logging

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
#define LL long long
map <LL, LL> a;
LL B, P, N, ans;
inline LL ceil (LL x){
    if (sqrt (x) * sqrt (x) != x)
        return sqrt (x) + 1;
    return sqrt (x);
}
int main (){
    while (~scanf ("%lld %lld %lld", &P, &B, &N)){
        LL len = ceil (P), t = N, m = 1, n = 1;
        ans = 0;
        a.clear ();
        for (register int i = 1; i <= len; i ++){
            m = m * B % P;
            t = t * B % P;
            a[t] = i;
        }
        for (register int i = 1; i <= len; i ++){
            n = m * n % P;
            if (! a[n])
                continue;
            ans = 1;
            printf ("%I64d\n", i * len - a[n]);
            break;
        }
        if (! ans)
            printf ("no solution\n");
    }
}

三.进阶例题:计算机

1.题目

2.题解

这道题一共有三个问,我们一个一个的解答:

1.直接用快速幂算

2.x\equiv zy^{-1}(modp)


证明:(y^{-1}是y的逆元)

xy\equiv z(modp)

xy*y^{-1}\equiv z*y^{-1}(modp)

x\equiv zy^{-1}(modp)


3.用BSGS的模板

就这样就完的。

但是,有一个细节需要扣。就是z和y在运算前需要模p,因为在运算前我们还要判断y等于0时,z是否等于0,是则输出1,否则输出无解。

3.代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;
#define LL long long
LL T, K, y, z, p;
map <LL, LL> A;
LL qkpow (LL a, int b){
    LL sum = 1;
    while (b > 0){
        if (b % 2 == 1)
            sum = sum * a % p;
        a = a * a % p;
        b /= 2;
    }
    return sum;
}
void BSGS (){
    if(y == 0 && z == 0){printf("1\n"); return ;}
    if(y == 0 && z != 0){printf("Orz, I cannot find x!\n"); return ;}
    LL len = ceil (sqrt (double (p))), t = z, m = 1, n = 1;
    A.clear ();
    for (int i = 1; i <= len; i ++){
        t = t * y % p;
        m = m * y % p;
        A[t] = i;
    }
    for (int i = 1; i <= len; i ++){
        n = n * m % p;
        if (! A[n])
            continue;
        printf ("%lld\n", i * len - A[n]);
        return ;
    }
    printf ("Orz, I cannot find x!\n");
}
int main (){
    scanf ("%lld %lld", &T, &K);
    while (T --){
        scanf ("%lld %lld %lld", &y, &z, &p);
        if (K == 1)
            printf ("%lld\n", qkpow (y, z));
        y %= p;
        z %= p;
        if (K == 2){
            if (y == 0 && z != 0){
                printf ("Orz, I cannot find x!\n");
                continue;
            }
            LL x = qkpow (y, p - 2) * z % p;
            printf ("%lld\n", x);
        }
        if (K == 3){
            BSGS ();
        }
    }
    return 0;
}

谢谢!

发布了61 篇原创文章 · 获赞 32 · 访问量 8371

猜你喜欢

转载自blog.csdn.net/weixin_43908980/article/details/88946187