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) 收藏 举报