POJ 2417

高次同余方程。   BL == N (mod P)

求解最小的L。由于数据范围很大,暴力不行

这里用到baby_step,giant_step算法。意为先小步,后大步。

令L=i*m+j  (m=ceil(sqrt(p-1))),

那么原式化为 B^(i*m)*B^j==N(MOD P)————》B^j===N*B^(-i*m)(MOD P)

我们先预处理B^0,B^1,B^2……B^(m-1),存入HASH表。,这一步就是baby-step,每次移动1

然后求出B^-m,枚举i,如果存在B^(-i*m)存在于HASH表中,说明存在解L=i*m+j    ,这一步为giant_step,每次移动m

以上 转 : http://blog.csdn.net/acm_cxlove/article/details/7831793

此处用的,其实是扩展的算法,不要求P为素数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int Maxn=65535;

struct hash{
	int a,b,next;
}Hash[Maxn*2];
int flag[Maxn+66];
int top,idx;

void insert(int a,int b){
	int k=b&Maxn;
	if(flag[k]!=idx){
		flag[k]=idx;
		Hash[k].next=-1;
		Hash[k].a=a;
		Hash[k].b=b;
		return ;
	}
	while(Hash[k].next!=-1){
		if(Hash[k].b==b) return ;
		k=Hash[k].next;
	}
	Hash[k].next=++top;
	Hash[top].next=-1;
	Hash[top].a=a;
	Hash[top].b=b;
}

int find(int b){
	int k=b&Maxn;
	if(flag[k]!=idx) return -1;
	while(k!=-1){
		if(Hash[k].b==b)
		return Hash[k].a;
		k=Hash[k].next;
	}
	return -1;
}

int gcd(int a,int b){
	return b==0? a:gcd(b,a%b);
}

int ext_gcd(int a,int b,int &x,int &y){
	int t,ret;
	if(!b){
		x=1; y=0;
		return a;
	}
	ret=ext_gcd(b,a%b,x,y);
	t=x; x=y; y=t-a/b*y;
	return ret;
}

int Inval(int a,int b,int n){
	int x,y,e;
	ext_gcd(a,n,x,y);
	e=(long long )x * b%n;
	return e<0?e+n:e;
}

int pow_mod(long long a,int b,int c){
	long long ret=1%c; a%=c;
	while(b){
		if(b&1)
		ret=ret*a%c;
		a=a*a%c;
		b=b>>1;
	}
	return ret;
}

int BabyStep(int A,int B,int C){
	top=Maxn; ++idx;
	long long buf=1%C,D=buf,K;
	int i,d=0,tmp;
	for(i=0;i<=100;buf=buf*A%C,i++){
		if(buf==B)
		return i;
	}
	while((tmp=gcd(A,C))!=1){
		if(B%tmp) return -1;
		++d;
		C/=tmp;
		B/=tmp;
		D=D*A/tmp%C;
	}
	int M=(int)ceil(sqrt((double)C));
	for(buf=1%C,i=0; i<= M; buf=buf*A%C,i++){
		insert(i,buf);
	}
	for(i=0,K=pow_mod((long long )A,M,C);i<=M;D=D*K%C,i++){
		tmp=Inval((int)D,B,C); int w;
		if(tmp>=0&&(w=find(tmp))!=-1)
		return i*M+w+d;
	}
	return -1;
}

int main(){
	int A,B,C;
	while(scanf("%d%d%d",&C,&A,&B)!=EOF){
		B=B%C;
	//	idx=0;
		int ans=BabyStep(A,B,C);
		if(ans==-1) printf("no solution\n");
		else printf("%d\n",ans);
	}
	return 0;
}

  

时间: 2024-11-08 19:29:30

POJ 2417的相关文章

Discrete Logging POJ - 2417(BSGS)

Discrete Logging POJ - 2417 题意:给P,B,N,求最小的L使得 BL≡N (mod P) Baby Step Giant Step 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #define ll long long 6 using namespace std; 7 const int maxn=76543;

poj 2417 Discrete Logging(A^x=B(mod c),普通baby_step)

http://poj.org/problem?id=2417 A^x = B(mod C),已知A,B,C,求x. 这里C是素数,可以用普通的baby_step. 在寻找最小的x的过程中,将x设为i*M+j.从而原始变为A^M^i * A^j = B(mod C),D = A^M,那么D^i * A^j = B(mod C ), 预先将A^j存入hash表中,然后枚举i(0~M-1),根据扩展欧几里得求出A^j,再去hash表中查找相应的j,那么x = i*M+j. 确定x是否有解,就是在循环i

POJ 2417 Discrete Logging 离散对数

链接:http://poj.org/problem?id=2417 题意: 思路:求离散对数,Baby Step Giant Step算法基本应用. 以下转载自:AekdyCoin [普通Baby Step Giant Step] [问题模型] 求解 A^x = B (mod C) 中 0 <= x < C 的解,C 为素数 [思路] 我们可以做一个等价 x = i * m + j  ( 0 <= i < m, 0 <=j < m) m = Ceil ( sqrt( C

BSGS算法+逆元 POJ 2417 Discrete Logging

POJ 2417 Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4860   Accepted: 2211 Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarith

离散对数,giant-step baby-step,拓展giant-step baby-step (poj 2417, hdu 2815)

普通giant-step baby-step: poj 2417 题意: B^L==N(MOD P), 给出P,B,N, 求最小的非负L. 限制: 2 <= P < 2^31 && P为素数; 2 <= B <P; 1 <= N < P 思路: 离散对数,用giant-step baby-step解决. 普通giant-step baby-step过程,要求P为素数: 令s = ceil(sqrt(P)), 则L = b * s + r (0 <=

[poj 2417]Discrete Logging 数论 BSGS

Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3516   Accepted: 1651 Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, base B, modulo P.

poj 2417 Discrete Logging 数论baby_step,giant_step算法

题意: 给p,b,n求最小的l使b^l==n(mod p). 题意: 相当于在0~p-1内搜索l满足同余式,baby_step,giant_step相当于分块的二分搜索,设m=sqrt(p), 则将p分为m*m,在m块内每块进行m个数的二分搜索. 代码: //poj 2417 //sep9 #include <iostream> #include <cmath> #include <algorithm> using namespace std; const int ma

【POJ 2417】 Discrete Logging

[题目链接] http://poj.org/problem?id=2417 [算法] Baby-Step,Giant-Step算法 [代码] #include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <

离散对数二连 poj 2417 Discrete Logging &amp; HDU 2815 Mod Tree

题目就不贴了.都是一样的套路求解a^x % c = b的最小x 注意HDU的题目很坑,有b比c大和题目中输出信息为全角引号的坑 下面贴的是HDU的版本,poj的改一下a,b,c顺序和输出就好 #include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; #define MOD 999

POJ 2417 Discrete Logging

http://www.cnblogs.com/jianglangcaijin/archive/2013/04/26/3045795.html 给p,a,b求a^n==b%p 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #include<map> 7 #define ll lon