1. 程式人生 > >BSGS(大小步)算法

BSGS(大小步)算法

res CA eof lib lse long ++ mod cstring

BSGS算法主要用於求解形如ax≡b(mod p)的式子中x的值。

在這裏我們不妨設

x=k1*n-k2

這時我們就可以將式子轉化為

ak1*n≡b*ak2(mod p)

這裏的n我們設為√p,所以我們利用分塊的思想在塊數範圍內枚舉k1即可。那在考慮完k1和n之後我們再考慮一下如何找到k2,我們建立一個哈希表,將k2取0~n時的式子左邊的值模p然後將其映射到此時k2的取值。求最後答案時我們只需找到在k1最小時滿足條件的最大的k2即可。

模板(poj2417)

#include<iostream>
#include<cstdio>
#include<cstring>
#include
<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstdlib> #include<queue> #include<ctime> #include<vector> #include<set> #include<map> #include<stack> using namespace std; map<long long,long long>mp; inline
long long pw(long long a,long long p,long long mod){ long long res=1; while(p){ if(p&1)res=res*a%mod; a=a*a%mod; p>>=1; } return res; } int main(){ long long a,b,p,m,n,i,j,k,pl; while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF){ n
=ceil(sqrt(p)); mp.clear(); long long x=b%p; mp[x]=0; for(i=1;i<=n;i++){ x=x*a%p; mp[x]=i; } long long y=pw(a,n,p),ok=0; x=1; for(i=1;i<=n;i++){ x=x*y%p; if(mp[x]){ ok=1; pl=i; break; } } if(ok){ printf("%lld\n",((pl*n%p-mp[x])%p+p)%p); }else puts("no solution"); } return 0; }

BSGS(大小步)算法