您的位置:首页 > 其它

POJ 2417 Discrete Logging

2016-07-12 22:25 393 查看
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. That is, find an integer L such that

BL == N (mod P)

【题目分析】

同余方程组的题目。属于离散对数的范畴。但是这类题目并没有多项式的算法(那密码学还学什么呢)。所以只能枚举,(B^m)^i这样的枚举方式,可以尽量的减少搜索量。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
const int maxn=1000001;
using namespace std;
bool hash[maxn];
long long p[maxn],var[maxn];
inline void ins(long long n,long long v)
{
int x=v%maxn;
while (hash[x]&&var[x]!=v){x++;if(x==maxn)x=0;}
if (!hash[x]) var[x]=v,hash[x]=true,p[x]=n;
}
long long find(long long v)
{
int x=v%maxn;
while (hash[x]&&var[x]!=v)
{x++;if (x==maxn) x=0;}
if (hash[x]==false) return -1;
return p[x];
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if (!b) {x=1,y=0;return a;}
long long r=exgcd(b,a%b,x,y),t=x;
x=y; y=t-a/b*y; return r;
}
long long bsgs(long long a,long long b,long long p)
{
long long num=1;
int m=ceil(sqrt(p*1.0));
for (int i=0;i<m;++i) ins(i,num),num=num*a%p;
long long ret=1;
for (int i=0;i<m;++i)
{
long long x,y,r=exgcd(ret,p,x,y);
x=x*b;x=(x%(p/r)+(p/r))%(p/r);
long long ans=find(x);
if (ans!=-1) return (ans+i*m);
ret=ret*num%p;
}
return -1;
}
int main()
{
long long n,b,P;
while (scanf("%lld%lld%lld",&P,&b,&n)!=EOF)
{
memset(hash,0,sizeof hash);
memset(var,-1,sizeof var);
memset(p,-1,sizeof p);
long long ans=bsgs(b,n,P);
if (ans==-1) printf("no solution\n");
else printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj