离散对数(同余理论-BSGS算法)

用来求解如下同余方程x的最小正整数解:

a^x \equiv b(mod \,\, p)                          0 \leqslant x < p

p为质数,a、b、p已知,且 0 \leqslant a,b < p (如果a、b大于p,则对他们取模)

模板:(p为素数)

/*********************解法***********************/
 //BSGS算法
 //求 a^x === b(mod p) 中的x值-----------当前p为素数
 //实际运用中用自己的hash表代替map可防TLE
/*********************解法***********************/

LL

LL BSGS(LL a, LL b, LL p){
    a %= p; b %= p;
    map<LL, LL>h;
    
    LL m = ceil(sqrt(p)), x, y, d, t = 1, v = 1;
    for(LL i = 0; i < m; i++){
        if(h,count(t)) h[t] = min(h[t], i);
        else h[t] = i;
        t = (t * a) % p;
    }
    for(LL i = 0; i < m; i++){
        d = exgcd(v, p, x, y);
        x = (x * b/d % p + p) % p;
        if(h.count(x)) return i * m + h[x];
        v = (v * t) % p;
    }
    return -1;
}

扩展(p为非素数)

模板:

/*********************解法***********************/
 //BSGS算法
 //求 a^x === b(mod p) 中的x值-----------当前p为合数
 //注意:a,b,p分别为1,1,1时,结果x为1而非0
/*********************解法***********************/

LL exBSGS(LL a, LL b, LL ){
    a %= p; b %= p;
    LL res = 1;
    for(LL i = 0; i <= 50; i++){
        if(res == b) return i;
        res = (res * a) % p;
    }   //枚举比较小的
    
    LL x, y, d, , v = 1, cnt = 0;
    while(d = gcd(a, p) != 1){
        if(b % d) return -1;
        b /= d, p /= d;
        v = (v * (a/d)) % p;
        cnt++;
    } //约分直到(a,p) == 1;
    
    map<LL, LL> h;
    LL m = ceil(sqrt(p)), t = 1;
    for(LL i = 0; i < m; i++){
        if(h.count(t)) h[t] = min(h[t], i);
        else h[t] = i;
        t = (t * a) % p;
    }
    for(LL i = 0; i < m; i++){
        d = exgcd(v, p, x, y);
        x = ((x * (b/d)) % p + p) % p;
        if(h.count(x)) return i * m + h[x] + cnt;
        v = (v * t) % p;
    }
    return -1;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章