DestinHistoire

 

BZOJ-2242 [SDOI2011]计算器(快速幂+exgcd+BSGS)

题目描述

  给出 \(a,b,p\),分别求 \(a^b\mod p\)\(ax\equiv b\pmod p\) 的最小 \(x\)\(a^x\equiv b\pmod p\) 的最小 \(x\)

  数据范围:\(1\leq T\leq 10,1\leq a,b,p\leq 10^9\)\(p\) 为质数。

分析

  三合一,\(\text{BSGS}\) 部分注意特判 \(a\)\(p\) 的倍数的情况。

代码

#include<bits/stdc++.h>
using namespace std;
long long quick_pow(long long a,long long b,long long mod)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
long long a,b,x,y;
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    long long gcd=exgcd(b,a%b,x,y);
    long long temp=x;x=y;y=temp-y*(a/b);
    return gcd;
}
map<long long,long long> mp;
long long BSGS(long long a,long long b,long long p)
{
    long long m=sqrt(p)+1;
    if(a%p==0&&b!=0)
        return -1;
    mp.clear();
    long long ans=b;
    for(int i=0;i<m;i++)
    {
        mp[ans]=i;
        ans=1ll*ans*a%p;
    }
    long long temp=quick_pow(a,m,p);
    ans=1;
    for(int i=1;i<=m;i++)
    {
        ans=1ll*ans*temp%p;
        if(mp.count(ans))
            return i*m-mp[ans];
    }
    return -1;
}
int main()
{
    int T,op;
    cin>>T>>op;
    while(T--)
    {
        long long a,b,p;
        cin>>a>>b>>p;
        if(op==1)
            cout<<quick_pow(a,b,p)<<endl;
        if(op==2)
        {
            int gcd=__gcd(a,p);
            if(b%gcd!=0)
                puts("Orz, I cannot find x!");
            else
            {
                a=a/gcd,p=p/gcd;
                exgcd(a,p,x,y);
                cout<<(x*b%p+p)%p<<endl;
            }
        }
        if(op==3)
        {
            if(BSGS(a,b,p)==-1)
                puts("Orz, I cannot find x!");
            else
                cout<<BSGS(a,b,p)<<endl;
        }
    }
    return 0;
}

posted on 2020-11-09 22:11  DestinHistoire  阅读(72)  评论(0)    收藏  举报

导航