【bzoj2242】 SDOI2011—计算器

http://www.lydsy.com/JudgeOnline/problem.php?id=2242 (题目链接)

题意

  给出y,z,p。求:1.yz mod p;2.xy=z(mod p);3.yx=z(mod p)。

Solution

  1.快速幂

  2.exgcd

  3.BSGS

细节

  数学题就是细节多,具体看代码。

代码

// bzoj2242
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

map<int,int> mp;

LL power(LL a,LL b,LL c) {
	LL res=1;
	while (b) {
		if (b&1) res=res*a%c;
		b>>=1;a=a*a%c;
	}
	return res;
}
void exgcd(LL a,LL b,LL &d,LL &x,LL &y) {
	if (b==0) {d=a;x=1;y=0;return;}
	exgcd(b,a%b,d,y,x);
	y-=a/b*x;
}
LL BSGS(LL a,LL b,LL p) {   //求解a^x=b(mod p),p为素数,无解返回-1.
	if (a%p==0 && b==0) return 1;
	if (a%p==0) return -1;
	mp.clear();mp[1]=0;   //注意a^0=1
	int m=ceil(sqrt(p));   //向上取整,避免漏解
	LL inv=power(a,p-m-1,p),e=1;   //inv为a^m的逆元,用费马小定理求
	for (int i=1;i<m;i++) {   //求e[i]数组
		e=e*a%p;
		if (!mp.count(e)) mp[e]=i;
	}
	for (int i=0;i<m;i++) {   //枚举a^(im),a^(im+1),a^(im+2)~~~
		if (mp.count(b)) return mp[b]+i*m;   //一定要是mp.count(),因为mp[b]可能为0
		else b=b*inv%p;
	}
	return -1;
}
int main() {
	LL T,K,Y,Z,P;scanf("%lld%lld",&T,&K);
	while (T--) {
		scanf("%lld%lld%lld",&Y,&Z,&P);
		if (K==1) printf("%lld\n",power(Y,Z,P));
		if (K==2) {
			LL x,y,d;
			exgcd(Y,P,d,x,y);
			if (Z%d!=0) puts("Orz, I cannot find x!");
			else printf("%lld\n",((Z/d)*x%(P/d)+(P/d))%(P/d));
		}
		if (K==3) {
			LL ans=BSGS(Y,Z,P);
			if (ans==-1) puts("Orz, I cannot find x!");
			else printf("%lld\n",ans);
		}
	}
	return 0;
}

  

  

posted @ 2016-12-20 20:17  MashiroSky  阅读(225)  评论(0编辑  收藏  举报