poj2417 Discrete Logging(BSGS:Baby Step Giant Step)

来源:互联网 发布:男友一夜 知乎 编辑:程序博客网 时间:2024/06/05 15:36

Discrete Logging
Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 4283 Accepted: 1970

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)

Input

Read several lines of input, each containing P,B,N separated by a space.

Output

For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".

Sample Input

5 2 15 2 25 2 35 2 45 3 15 3 25 3 35 3 45 4 15 4 25 4 35 4 412345701 2 11111111111111121 65537 1111111111

Sample Output

013203120no solutionno solution19584351462803587

Hint

The solution to this problem requires a well known result in number theory that is probably expected of you for Putnam but not ACM competitions. It is Fermat's theorem that states 
   B(P-1) == 1 (mod P)

for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m 
   B(-m) == B(P-1-m) (mod P) .

题意:求L使B的L次幂与N对P同余。

题目很短,一开始以为是数学题,想着还要推公式,好麻烦。后来才发现有hint,但是并没有什么用,因为按公式敲完一定会超时。学长说用BSGS做,就找了一下模板,半知半解吧,没有完全搞懂,就当收集了一个新模板吧,感觉BSGS算法大多是都是解数学题,以后再做类似题的时候再做扩展。

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#define maxn 76567using namespace std;int head[maxn], nextt[maxn], e[maxn], cnt, hash[maxn];int find(int x){    int k = x % maxn;    for(int i = head[k]; i != -1; i = nextt[i])    {        if(hash[i] == x)            return e[i];    }    return -1;}int BSGS(int b, int n, int p){    memset(head, -1, sizeof(head));    cnt = 1;    if(n == 1)        return 0;    int m = sqrt(p);    long long q = 1;    for(int i = 0; i < m; i++)    {        int k = ((q * n) % p) % maxn;        hash[cnt] = (q * n) % p;        e[cnt] = i;        nextt[cnt] = head[k];        head[k] = cnt;        cnt++;        q = q * b % p;    }    int j;    long long x = 1;    for(long long i = m; ; i += m)    {        if((j = find(x = x * q % p)) != -1)            return i - j;        if(i > p)            break;    }    return -1;}int main(){    int p, n, b;    while(scanf("%d%d%d", &p, &b, &n) != EOF)    {        int ans = BSGS(b, n, p);        if(ans == -1)            printf("no solution\n");        else            printf("%d\n",ans);    }}


0 0
原创粉丝点击