[poj 2417] Discrete Logging · BSGS

2 篇文章 0 订阅
1 篇文章 0 订阅

BSGS,baby step giant step,大步小步法,很形象的概括了这个算法的核心,算法用于解决一个很经典的问题:

,给定A,B,P,其中P为素数,求一个可行解x

大步小步法算法详解:猛戳这里

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <cmath> 
using namespace std;
#define ll long long 

ll A,B,x,y,m,p,ans;
map<int,int> hash;
ll tmp,e,ny,sx;

ll pow(ll d,ll t){
	ll ret=1;
	for (;t;t>>=1,d=d*d%p)
		if (t&1) ret=ret*d%p;
	return ret;
}

int main(){
	#ifndef ONLINE_JUDGE
	freopen("2417.in","r",stdin);
	freopen("2417.out","w",stdout);
	#endif
	while (~scanf("%I64d%I64d%I64d",&p,&A,&B)){
		hash.clear();
		m=(int)sqrt(p+0.5);
		tmp=A;e=1;
		for (int i=0;i<=m;i++){ 
			if (!hash[e]) hash[e]=i+1; //因为0也能算答案,但是不好判断,所以强制+1,在38行算答案的时候会把这个1减掉 
			e=e*tmp%p;
		}
		
		ny=pow(pow(A,m),p-2);
		e=B;ans=-1;
		for (int i=0;i<=m;i++){ 
			if (hash[e]){
				ans=(hash[e]-1)+i*m;
				break;
			}
			e=e*ny%p;
		}
		if (ans==-1) puts("no solution");
			else printf("%I64d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值