離散對數(同餘理論-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;
}

 

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