bzoj 2242: [SDOI2011]计算器

Description

你被要求设计一个计算器完成以下三项任务:
1、给定y,z,p,计算Y^Z Mod P 的值;
2、给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数;
3、给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数。

Solution

打个 (BSGS) 板子
(x=a*m-b)
原式变为 (y^{a*m}=z*y^b\,\,(mod P))
枚举 (b=[0,m-1]) 求出所有的取值,并存下来
再枚举 (a) ,查找右边是否有出现过,由欧拉定理: (a) 不会超过 (frac{P}{m})
(y\%P==0) 时且 (P>1) 时无解,特判一下
(m=sqrt(P)) 时,复杂度最优

#include<bits/stdc++.h>
#define int long long
using namespace std;
int mod;
inline int qm(int x,int k){
	int sum=1;
	while(k){
		if(k&1)sum=1ll*sum*x%mod;
		x=1ll*x*x%mod;k>>=1;
	}
	return sum;
}
inline int exgcd(int a,int b,int &x,int &y){
	if(!b){x=1;y=0;return a;}
	int r=exgcd(b,a%b,y,x);y-=a/b*x;
	return r;
}
inline void solo(int a,int b,int c){
	int x,y,r;
	r=exgcd(a,b,x,y);
	if(c%r){puts("Orz, I cannot find x!");return ;}
	x*=c/r;b/=r;
	x=(x%b+b)%b;
	cout<<x<<endl;
}
//y^x=z (mod P)
map<int,int>a;
inline void bsgs(int y,int z){
	y%=mod;z%=mod;
	if(z==1){puts("0");return ;}
	if(y%mod==0){
		if(mod>1)puts("Orz, I cannot find x!");
		else puts("0");
		return ;
	}
	a.clear();
	int t=sqrt(mod),e=qm(y,t);
	for(int i=0;i<t;i++,z=1ll*z*y%mod)a[z]=i;
	for(int i=1,x=e;i<=t+1;i++,x=1ll*x*e%mod)
		if(a.find(x)!=a.end()){cout<<i*t-a[x]<<endl;return ;}
	puts("Orz, I cannot find x!");
}
main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  int T,K,y,z;
  cin>>T>>K;
  while(T--){
	  cin>>y>>z>>mod;
	  if(K==1)cout<<qm(y,z)<<endl;
	  else if(K==2)solo(y,mod,z);
	  else bsgs(y,z);
  }
  return 0;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8977753.html