【洛谷P2485】计算器

题目

题目链接:https://www.luogu.com.cn/problem/P2485
你被要求设计一个计算器完成以下三项任务:

  1. 给定\(y,z,p\),计算\(y^z \rm mod\ p\)的值;
  2. 给定\(y,z,p\),计算满足\(xy ≡z\pmod p\)的最小非负整数\(x\)
  3. 给定\(y,z,p\),计算满足\(y^x ≡z\pmod p\)的最小非负整数\(x\)

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

思路

就连智推都给我推模板了\(qwq\)

  1. 快速幂,时间复杂度\(O(\log n)\)
  2. 扩欧,时间复杂度\(O(\log n)\)
  3. \(\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;
}
posted @ 2020-01-29 14:37  stoorz  阅读(187)  评论(0编辑  收藏  举报