BZOJ_3239_Discrete Logging_BSGS

BZOJ_3239_Discrete Logging_BSGS

题意:Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 2 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that BL == N (mod P)

分析:BSGS裸题

数据很水,少了很多特判依然能过

BSGS思想核心思想:根号预处理+哈希/map

 

代码:

// luogu-judger-enable-o2
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
#include <math.h>
using namespace std;
#define LL long long
map<LL,int> mp; 
LL qp(LL x,LL y,LL mod){
	LL re=1;
	while(y){
		if(y&1ll)re=re*x%mod;
		x=x*x%mod;
		y>>=1ll;
	}
	return re;
}
void exgcd(LL a,LL b,LL &x,LL &y,LL &p){
	if(!b){x=1;y=0;p=a;return ;}
	exgcd(b,a%b,y,x,p);
	y-=(a/b)*x;
}
LL BSGS(LL n,LL a,LL b){
	if(n==1)if(!b)return a!=1; else return -1;
	if(b==1)if(a)return 0; else return -1;
	if(a%n==0)if(!b)return 1; else return -1;
	LL m=ceil(sqrt(n)),d=1,base=1;
	mp.clear();
	for(int i=0;i<m;i++)
	{
		if(!mp.count(base))mp[base]=i;
		base=(base*a)%n;
	}
	for(int i=0;i<m;i++)
	{
		LL x,y,s;
		exgcd(d,n,x,y,s);
		x=(x*b%n+n)%n;
		if(mp.count(x))return i*m+mp[x];
		d=(d*base)%n;
	}
	return -1;
}
int main()
{
	LL n,a,b;
	while(scanf("%lld%lld%lld",&n,&a,&b)!=EOF)
	{
		LL x=BSGS(n,a,b);
		if(x==-1)puts("no solution");
		else printf("%lld\n",x);
	}
}

 

posted @ 2018-03-17 22:19  fcwww  阅读(179)  评论(0编辑  收藏  举报