Baby-Step-Giant-Step

    BSGS算法用于解决形如:      A  ^  x  ≡  B  (  mod  C  ) 的问题。

   学这个算法前需要具备以下知识:快速幂取模、扩展欧几里得、同余知识、哈希表(也可以用map,不过更耗时).. 

  一.     普通的Baby-Step-Giant-Step

    对于普通的BSGS,使用时有个限制条件就是:C只能是一个素数。当C 不是素数的时候,便要用到扩展BSGS,我们先来看普通的…

    做法:首先令 x = a * m + b ;  m = ceil ( sqrt ( C ) ) ;  [ceil: 上取整] 0 <= a < m , 0 <= b < m ;

    Then 原式等价于 ( ( A ^ a ) ^ m ) * A ^ b ≡ B (mod C );

    Then 我们枚举a ,从0 到 m ,对每个a ,算出 A^a ,放到哈希表或map里(用哈希更高效…这里先用map) ,如 h=A^a; mp[h]=a;然后我们用 D 来表示 ( ( A ^ a ) ^ m ) ,用Y来表示 A^B 原式便可化为 : D * Y ≡ B (mod C);

    Then 我们再次枚举 a 从 0 到 m ,可以逐个算出 D 的值,在有了D值得基础上,运用扩展欧几里得可以算出 Y ,现在查找原本记录的表,查看这个Y 值是否存在,如果存在便可返回 a^m + b ;

    如果找完0 到 m ,依然没有发现可行的解,表示无解,退出。

    

 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<map>
 4 using namespace std;
 5 /*
 6   Baby-Step-Giant-Step:   用于解决形如: A^x = B (mod C) 的问题
 7   <><> 普通的解法只能解决C是素数的情况
 8   首先,令 x= a*m + b ; -- m= Ceil(sqrt(c));  --  Ceil 表示上取整
 9   then 原式等价于 ( (A^a )^m )*(A^b)=B (mod c);
10   then 那么我们可以枚举 a: 0-m ,记录到 (a,A^a) ,用H 来表示: (A^a)^m ;
11   那么 原式等价于 H * A^b = B (mod c) ;
12   then 求出 A^m ; 枚举 a: 0-m ,对于每个值判断有没有 A^b 存在,如果有便退出...
13 */
14 // 这个代码不敢保证正确无误,因为没有找到题来A,不过思路应该是没错
15 //了解了普通的BSGS,可以去看下面那份代码,注释得比较详细...
16 #define EPS 0.0000001
17 typedef long long LL;
18 LL pow(LL a,LL b,LL c)    //快速幂取模
19 {
20   LL ans=1;
21   while(b>0)
22   {
23     if(b&1)
24     {
25       ans=ans*a%c;
26     }
27     a=a*a%c;
28     b>>=1;
29   }
30   return ans;
31 }
32 void exGcd(LL a,LL b,LL &d,LL &x,LL &y)
33 {
34   if(b==0)
35   {
36     d=a;
37     x=1;
38     y=0;
39     return ;
40   }
41   exGcd(b,a%b,d,x,y);
42   LL t=x;
43   x=y;
44   y=t-a/b*y;
45 }
46 LL BSGS(LL A,LL B,LL C)
47 {
48   map<LL,int> mp;
49   // LL m=(LL)ceil(sqrt(C));  据英明神武的某朱说Gcc不支持这个ceil
50   LL m=(LL)(sqrt(C)+1-EPS);
51   for(int i=m-1;i>=0;i--)
52   {
53     LL h=pow(A,i,C);
54     mp[h]=i;
55   }
56   LL h=pow(A,m,C);
57   LL d,x,y;
58   for(int i=0;i<m;i++)
59   {
60     LL k=pow(h,i,C);
61     exGcd(k,C,d,x,y);
62     if(B%d!=0) continue;
63     x=((x*B/d%C)+C)%C;
64     if(mp.find(x)!=mp.end()) return mp[x]+i*m;
65   }
66   return -1;
67 }
68 int main()
69 {
70   LL A,B,C;
71   while(scanf("%I64d%I64d%I64d",&A,&B,&C)!=EOF)
72   {
73     printf("%I64d\n",BSGS(A,B,C));
74   }
75   return 0;
76 }
代码

相关文章:

  • 2021-10-09
  • 2021-09-15
  • 2022-12-23
  • 2022-12-23
  • 2021-11-17
  • 2021-09-28
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-07-19
  • 2021-07-06
  • 2021-07-17
  • 2022-03-07
  • 2022-12-23
相关资源
相似解决方案