【洛谷P2485】计算器
题目
题目链接:https://www.luogu.com.cn/problem/P2485
你被要求设计一个计算器完成以下三项任务:
- 给定\(y,z,p\),计算\(y^z \rm mod\ p\)的值;
- 给定\(y,z,p\),计算满足\(xy ≡z\pmod p\)的最小非负整数\(x\);
- 给定\(y,z,p\),计算满足\(y^x ≡z\pmod p\)的最小非负整数\(x\)。
为了拿到奖品,全力以赴吧!
思路
就连智推都给我推模板了\(qwq\)。
- 快速幂,时间复杂度\(O(\log n)\)
- 扩欧,时间复杂度\(O(\log n)\)
- \(\rm BSGS\),时间复杂度\(O(\sqrt{n})\)。
代码
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int T,type;
ll a,b,p;
ll power(ll x,ll k,ll MOD)
{
ll ans=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) ans=ans*x%MOD;
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if (!b)
{
x=1; y=0;
return a;
}
ll d=exgcd(b,a%b,x,y);
ll temp=x; x=y; y=temp-a/b*y;
return d;
}
ll BSGS(ll a,ll b,ll p)
{
map<ll,int> hash;
ll t=ceil(sqrt(p));
for (int i=0;i<=t;i++)
hash[b*power(a,i,p)%p]=i;
a=power(a,t,p);
for (int i=1;i<=t;i++)
{
ll val=power(a,i,p);
if (hash[val]) return ((i*t-hash[val])%p+p)%p;
}
return -1;
}
int main()
{
scanf("%d%d",&T,&type);
while (T--)
{
scanf("%lld%lld%lld",&a,&b,&p);
if (type==1) printf("%lld\n",power(a,b,p));
if (type==2)
{
ll x,y,d=exgcd(a,p,x,y),MOD=p/d;
if (b%d) printf("Orz, I cannot find x!\n");
else printf("%lld\n",(b/d*x%MOD+MOD)%MOD);
}
if (type==3)
{
ll ans=BSGS(a,b,p);
if (ans>0) printf("%lld\n",ans);
else printf("Orz, I cannot find x!\n");
}
}
return 0;
}