poj 3243 Clever Y&&hdu 2815 Mod Tree(扩展baby_step)

http://poj.org/problem?id=3243


求A^x = B(mod C)中的x ,C是任意的数。


框架都在这里了:http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4

理解:http://blog.csdn.net/ivan_zjj/article/details/7597109


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)

using namespace std;
const int maxn = 99991;

bool hash[maxn+10];
int idx[maxn+10];
LL val[maxn+10];

LL gcd(LL a, LL b)
{
	if(b == 0)
		return a;
	return gcd(b,a%b);
}
void extend_gcd(LL a, LL b, LL &x, LL &y)
{
	if(b == 0)
	{
		x = 1;
		y = 0;
		return;
	}
	extend_gcd(b,a%b,x,y);
	LL t = x;
	x = y;
	y = t-a/b*y;
}
void insert(int id, LL vv)
{
	LL v = vv%maxn;
	while(hash[v] && val[v] != vv)
	{
		v++;
		if(v == maxn)
			v -= maxn;
	}
	if(hash[v] == false)
	{
		hash[v] = true;
		idx[v] = id;
		val[v] = vv;
	}
}

int found(LL vv)
{
	LL v = vv%maxn;
	while(hash[v] && val[v] != vv)
	{
		v++;
		if(v == maxn)
			v -= maxn;
	}
	if(hash[v] == false)
		return -1;
	return idx[v];
}

LL baby_step(LL A, LL B, LL C)
{
	memset(hash,false,sizeof(hash));
	memset(idx,-1,sizeof(idx));
	memset(val,-1,sizeof(val));
	//首先特判log(C)以内的解。因为下面消因子法解出来的x >= b,但有可能x的解是小于b的。所以先特判。
	LL ans = 1;
	for(int i = 0; i <= 50; i++)
	{
		if(ans == B)
			return i;
		ans = ans*A%C;
	}
	//消因子,直到gcd(A,C) = 1,就可以用普通的baby_step
	LL D = 1%C,tmp;
	LL b = 0;
	while((tmp = gcd(A,C)) != 1)
	{
		if(B%tmp)
			return -1;
		b++;
		B = B/tmp;
		C = C/tmp;
		D = D*A/tmp%C;
	}
	LL M = ceil(sqrt(C*1.0));
	LL k = 1;
	for(int i = 0; i < M; i++)
	{
		insert(i,k);
		k = k*A%C;
	}
	LL x,y;
	for(int i = 0; i < M; i++)
	{
		extend_gcd(D,C,x,y);
		x = x*B;
		x = (x%C+C)%C;
		int jj = found(x);
		if(jj != -1)
			return (LL)i*M+(LL)jj+b;
			
		D = D*k%C;
	}
	return -1;
}

int main()
{
	LL A,B,C;
	while(~scanf("%lld %lld %lld",&A,&C,&B))
	{
		if(A == 0 && B == 0 && C == 0) break;
		LL ans = baby_step(A,B,C);
		if(ans == -1)
			printf("No Solution\n");
		else
			printf("%lld\n",ans);
	}
	return 0;
}


你可能感兴趣的:(扩展baby_step)