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;
}

posted @ 2018-05-01 22:03  PIPIBoss  阅读(216)  评论(0编辑  收藏  举报