lougu 2485计算器(BSGS)

简介: lougu 2485计算器(BSGS)

你被要求设计一个计算器完成以下三项任务:


1、给定y、z、p,计算y^z mod p 的值;


2、给定y、z、p,计算满足xy ≡z(mod p)的最小非负整数x;


3、给定y、z、p,计算满足y^x ≡z(mod p)的最小非负整数x。


为了拿到奖品,全力以赴吧!


思路:

对于询问1,快速幂解决


对于询问2,扩展欧几里得解决


对于询问3,采用BSGS算法

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p, a, b;
ll qmul(ll a, ll b, ll mod) {
    ll ans = 0;
    while (b) {
        if (b & 1) {
            ans = (ans + a) % mod;
        }
        a = (a + a) % mod;
        b >>= 1;
    }
    return ans % mod;
}
ll qpow(ll a, ll b, ll mod) {
    ll ans = 1;
    while (b) {
        if (b & 1) {
            ans = (ans * a) % mod;
        }
        a = (a * a) % mod;
        b >>= 1;
    }
    return ans % mod;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
    if (!b) {
        x = 1; y = 0;
        return a;
    } else {
        ll d = exgcd(b, a % b, y, x);
        y -= a / b * x;
        return d;
    }
}
ll bsgs(ll a, ll b, ll p) {
    b%=p;a%=p;
    ll n = sqrt(p) + 1;
    map<ll,ll> mp;
    mp.clear();
    ll ans = b%p;
    if (a == 0 && b == 0) return 0;
    if (a == 0 && b != 0) return -1;
    for (int i = 0; i <= n; i++) {
        mp[ans] = i;
        ans = qmul(ans, a, p);
    }
    ans = 1;
    for (int i = 1; i <= n; i++) ans = qmul(ans, a, p);
    ll ret = 1;
    for (int i = 1; i <= n; i++) {
        ret = qmul(ret, ans, p);
        if (mp[ret] != 0) {
            return (ll)i * n - mp[ret];
        }
    }
    return -1;
}
int main() {
    int n, opt;
    ll a, b, p, x, y;
    while (scanf("%d%d", &n, &opt) != EOF) {
        for (int i = 1; i <= n; i++) {
            scanf("%lld%lld%lld", &a, &b, &p);
            if (opt == 1) {
                printf("%lld\n", qpow(a, b, p));
            } else if (opt == 2) {
                ll d = exgcd(a, p, x, y);
                if (b % d != 0) {
                    printf("Orz, I cannot find x!\n");
                } else {
                    x = qpow(a, p - 2, p) * b % p;
                    printf("%lld\n", x);
                }
            } else {
                ll ans = bsgs(a, b, p);
                if (ans == -1) {
                    printf("Orz, I cannot find x!\n");
                } else {
                    printf("%lld\n", ans);
                }
            }
        }
    }
    return 0;
}
相关文章
|
3月前
计算器V1
创建一个简单的计算器程序,能执行整数的加、减、乘、除和求余运算。用户输入格式为:操作数1 运算符op 操作数2。遇到除数为0时,输出&quot;Division by zero!&quot;;运算符非法则输出&quot;Invalid operator!&quot;。示例输入和输出已给出。
38 0
|
3月前
计算器V2
编写了一个简单的程序,实现了浮点数的加、减、乘、除和幂运算。程序包括了对浮点数的计算,并展示了运算结果。其中,幂运算需包含&quot;math.h&quot;头文件。
26 0
|
3月前
|
前端开发 JavaScript
使用html+css+javaScript 完成计算器
使用html+css+javaScript 完成计算器
|
Java
从计算器小例子的总结思考
从计算器小例子的总结思考
106 0
|
3月前
leetcode-224:基本计算器
leetcode-224:基本计算器
23 0
|
8月前
|
Java
计算器的模拟实现
计算器的模拟实现
75 0
|
11月前
一个计算器器脚本
一个计算器器脚本
50 1
|
11月前
|
C++
C++ 计算器实现加减乘除
C++ 计算器实现加减乘除
|
前端开发
一个很简易的计算器
一个很简易的计算器
88 0
一个很简易的计算器