码迷,mamicode.com
首页 > 编程语言 > 详细

BSGS(大小步)算法

时间:2018-06-09 18:50:40      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:++   lin   scanf   namespace   http   set   map   pac   ace   

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(大小步)算法

标签:++   lin   scanf   namespace   http   set   map   pac   ace   

原文地址:https://www.cnblogs.com/yzxverygood/p/9160401.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!