bsgs算法詳解


例題  poj 2417bsgs  http://poj.org/problem?id=2417

這是一道bsgs題目,用bsgs算法,又稱大小步(baby step giant step)算法,或者拔(b)山(s)蓋(g)世(s)算法,或者北(b)上(s)廣(g)深(s)算法。。。

題目大意就是

給定a,b,p,求最小的非負整數x,滿足  ax ≡ b(mod p)

 

先令 x = i*m-j,其中 m=ceil(sqrt(p)),ceil是向上取整。

這樣原式就變為     ai*m-j = b (mod p),

移項就變成了        ai*m = b*aj (mod p)

枚舉j (范圍0-m) ,將 b*aj  存入hash表。

枚舉i (范圍1-m) ,從hash表中尋找第一個滿足ai*m = b*aj  (mod p)。

此時   x = i*m-j  就是所要求的。

 

那么為什么只計算到 m=ceil(sqrt(q))  就可以確定答案呢?

因為 x = i*m-j , 所以x 的最大值不會超過p

a(k mod p-1) = ak (mod p)  證明這個公式,(需要用到費馬小定理)

k mod p-1 就是 k-m(p-1) ,原式就變成了 ak-m(p-1) ≡ ak (mod p)

再變一步  a/ am(p-1) ≡ ak (mod p)

這時讓 am(p-1) ≡ 1 (mod p) 就行了。

由費馬小定理知: 當p為質數且 (a,p時 ap-1 ≡ (mod p)

所以推出 為質數 且 (a,p)=1 這個條件, 所以 a(k mod p-1) ≡ (mod p) 

所以:如果枚舉 的話枚舉到 p 即可。

所以使 imj<=p , 即 m=⌈√p⌉ , i,最大值也為m。

 

 這是代碼,結合上面的看

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<map>
 4 #include<cmath>
 5 
 6 using namespace std;
 7 typedef long long ll;
 8 
 9 map<ll,int>mp;
10 ll p,a,b;
11 ll n,m,now,ans,t;
12 bool flag;
13 
14 ll fast_pow(ll x)
15 {
16     ll sum = 1;
17     ll aa = a;
18     while (x>0)
19     {
20         if (x&1) 
21             sum = (sum*aa)%p;
22         x = x>>1;
23         aa = (aa*aa)%p;
24     }
25     return sum;
26 }
27 int main()
28 {
29     while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF)
30     {
31         if(a%p==0)
32         {
33             printf("no solution\n");
34             continue;
35         }
36         mp.clear();
37         m = ceil(sqrt(p));
38         flag = false ;
39         now = b%p;        //b*a^j 當j==0時 
40         mp[now] = 0;
41         for(int i=1;i<=m;++i)
42         {
43             now = (now*a)%p;
44             mp[now] = i;
45         }
46         t = fast_pow(m);
47         now = 1;
48         for(int i=1;i<=m;++i)    //枚舉 (a^m)^i
49         {
50             now = (now*t)%p;
51             if(mp[now])
52             {
53                 flag = true;
54                 ans = i*m-mp[now];
55                 printf("%lld\n",(ans%p+p)%p);    //printf("%lld\n",(ans%p+p)%p);
56                 break;
57             }
58         }
59         if(!flag) printf("no solution\n");
60     }
61     return 0;
62 }
bsgs

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM