poj2417(Baby-Step Giant-Step)
题目链接:http://poj.org/problem?id=2417
题意:求满足给出 P, N, B, 求满足条件 BL == N (mod P) 的最小 L, 若不存在则输出 no solution.
思路:Baby-Step Giant-Step 算法
设 L = kt − m,其中 t = ⌊sqrt(L)⌋, 0 <= m < t.那么 B^L = N (mod P) 就等价于 B^(kt − m) = N (mod P) 即 B^(kt) ∗ N^(−1) = B^m (mod P).我们可以先预处理出所有的 Bi (0 <= i < t) 记录在一个 hash 表里,然后枚举 k,计算 B^(kt) ∗ N^(−1) 的值,在hash表里找是否有符和条件的 m,若有则 kt − m 就是答案之一.所有答案中取最小的一个即可。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #define ll long long 5 using namespace std; 6 7 const int MOD = 76543; 8 int hs[MOD], head[MOD], next[MOD], id[MOD], top; 9 10 void insert(int x, int y){ 11 int k = x % MOD; 12 hs[top] = x; 13 id[top] = y; 14 next[top] = head[k]; 15 head[k] = top++; 16 } 17 18 int find(int x){ 19 int k = x % MOD; 20 for(int i = head[k]; i != -1; i = next[i]){ 21 if(hs[i] == x) return id[i]; 22 } 23 return -1; 24 } 25 26 int BSGS(int a, int b, int n){ 27 memset(head, -1, sizeof(head)); 28 top = 1; 29 if(b == 1) return 0; 30 int m = sqrt(n * 1.0), j; 31 ll x = 1, p = 1; 32 for(int i = 0; i < m; ++i, p = p * a % n) insert(p * b % n, i); 33 for(ll i = m; ; i += m){ 34 if( (j = find(x = x * p % n)) != -1 ) return i - j; 35 if(i > n) break; 36 } 37 return -1; 38 } 39 40 int main(void){ 41 int P, N, B; 42 while(~scanf("%d%d%d", &P, &B, &N)){ 43 int ans = BSGS(B, N, P); 44 if(ans == -1) printf("no solution\n"); 45 else printf("%d\n", ans); 46 } 47 return 0; 48 }
我就是我,颜色不一样的烟火 --- geloutingyu