【bzoj2242】[SDOI2011]计算器 快速幂+BSGS

第一问,快速幂
第二问,exgcd或
p是质数,所以y一定有逆元
x=y^(-1)*z
其中y^(-1)=y^(P-2)
因为0没有逆元,所以只有y=0时无解
第三问,BSGS
设x=bk+c
其中k=sqrt(P),b和c都小于sqrt(P)
Y^(bk+c)=Z
Y^(bk)=Z*Y^(-c)
用map记录一下Z*Y^(-c),一共sqrt(P)个数
枚举b,查询有没有对应的Z*Y^(-c),如果有,则更新答案
0要特判

复杂度O(sqrt(P)*logP)


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream> 
#include<map>

using namespace std;

int mod,y,z,k,T,n;
map<int,int> mp;

int power(int x,int y,int mod)
{
	int ans=1;
	while (y)
	{
		if (y&1) ans=(long long)ans*x%mod;
		x=(long long)x*x%mod;
		y>>=1;
	}
	return ans;
}

void BSGS(int y,int z,int mod)
{
	if (y==0 && z==0) {printf("1\n");return;}
	if (y==0 && z!=0) {printf("Orz, I cannot find x!\n");return;}
	mp.clear();
	int temp=1,p=power(y,mod-2,mod),k=ceil(sqrt(mod));
	mp[z]=k+1;
	for (int i=1;i<k;i++)
	{
		temp=(long long)temp*p%mod;
		int t=(long long)temp*z%mod;
		if (!mp[t]) mp[t]=i;
	}
	temp=1;p=power(y,k,mod);
	for (int i=0;i<k;i++,temp=(long long)temp*p%mod)
	{
		if (mp[temp])
		{
			if (mp[temp]==k+1) printf("%d\n",i*k);
			else printf("%d\n",i*k+mp[temp]);
			return;
		}
	}
	printf("Orz, I cannot find x!\n");
}

int main()
{
	scanf("%d%d",&n,&T);
	for (int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&y,&z,&mod);
		y%=mod;
		if (T==1) printf("%d\n",power(y,z,mod));
		else
		if (T==2)
		{
			z%=mod;
			if (y==0 && z!=0) printf("Orz, I cannot find x!\n");
			else printf("%d\n",(long long)z*power(y,mod-2,mod)%mod);
		}
		else z%=mod,BSGS(y,z,mod);
	}
	return 0;
}


你可能感兴趣的:(【bzoj2242】[SDOI2011]计算器 快速幂+BSGS)