浙江理工大学每日一题——快速幂,线性同余方程,BSGS

题目描述
原题来自:SDOI 2011
你被要求设计一个计算器完成以下三项任务:
给定 y,z,py,z,p,计算 y^x\bmod pyz
modp 的值;
给定 y,z,py,z,p,计算满足 x\times y\equiv z\ (\bmod p\ )x×y≡z (modp ) 的最小非负整数 xx;
给定 y,z,py,z,p,计算满足 y^x\equiv z\ (\bmod p\ )yx≡z (modp ) 的最小非负整数 xx。
输入
输入包含多组数据。
第一行包含两个正整数 T,KT,K 分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同);
以下 TT 行每行包含三个正整数 y,z,py,z,p,描述一个询问。
输出
对于每个询问,输出一行答案。
对于询问类型 22 和 33,如果不存在满足条件的,则输出 Orz, I cannot find x!,注意逗号与 I 之间有一个空格。
样例输入 Copy
【样例输入1】
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
样例输出 Copy
【样例输出1】
2
1
2
【样例输出2】
2
1
0
提示
数据范围与提示
对于全部数据,1\le y,z,p\le 10^9,1\le T\le 101≤y,z,p≤109,1≤T≤10,且保证 pp 为质数。

点击查看代码
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll y, z, p;
ll ksm(ll x, ll y, ll mod)
{
    ll result = 1;
    while (y > 0)
    {
        if (y % 2 == 0)
        {
            y = y / 2;
            x = x * x % mod;
        }
        else
        {
            y--;
            result = result * x % mod;
            y = y / 2;
            x = x * x % mod;
        }
    }
    return result;
}
ll exgcd(ll a, ll b, ll &x, ll &yy)
{
    if (b == 0)
    {
        x = 1;
        yy = 0;
        return a;
    }
    ll gcd = exgcd(b, a % b, x, yy);
    ll tmp = x;
    x = yy;
    yy = tmp - a / b * yy;
    return gcd;
}
ll BSGS(ll a, ll b, ll n)
{
    a %= n;
    b %= n;
    if (a == 0)
        return b == 0 ? 1 : -1;
    if (b == 1)
        return 0;
    map<ll, ll> hash;
    ll t = sqrt(n) + 1;
    hash.clear();
    for (int i = 0; i < t; i++)
    {
        ll x = b * ksm(a, i, n) % n;
        hash[x] = i;
    }
    a = ksm(a, t, n);
    for (int i = 1; i <= t; i++)
    {
        ll ans = ksm(a, i, n);
        if (hash[ans])
            return i * t - hash[ans];
    }
    return -1;
}
int main()
{
    int t, k;
    cin >> t >> k;
    while (t--)
    {
        cin >> y >> z >> p;
        if (k == 1)
            cout << ksm(y, z, p) << "\n";
        else if (k == 2)
        {
            ll x, yy;
            ll gcd = exgcd(y, p, x, yy);
            if (z % gcd)
                cout << "Orz, I cannot find x!" << endl;
            else
            {
                x = x * z / gcd;
                x = (x % p + p) % p;
                cout << x << endl;
            }
        }
        else
        {
            ll ans = BSGS(y, z, p);
            if (ans != -1)
                cout << ans << "\n";
            else
                puts("Orz, I cannot find x!");
        }
    }
    system("pause");
    return 0;
}
posted @   美羊羊给沸羊羊搬砖  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示