BSGS algorithm (template)

BSGS (big small step algorithm)

Known \ (A, B, C \) , find \ (X \) . Order \ (A ^ X \ equiv B \ PMOD C \) .

step

\ [m = \ lceil \ sqrtc \ \ rceil \] \ [X = I * MJ \ \ (I \ in [. 1, m], J \ in [0, m]) \] \ [A ^ {I * } MJ \ equiv B \ PMOD C \] \ [A ^ {m} * I \ * A B equiv ^ J \ PMOD C \]
enum \ (a ^ j (j \ in [0, m]) \) Add \ (the hash \) table inside, and then enumerate \ (a ^ {m} * I \) , in \ (the hash \) table look inside the same there, the same as if it exists.

If the interrogation in the case of more, can be \ (BM = \ lceil {C ^ \ FRAC. 3} {2} {} \ rceil \) , \ (GM = \ lceil {C ^ \ FRAC. 1 {{}. 3 }} \ rceil \) \ ((I \ in [. 1, GM], J \ in [0, BM]) \)

Implementation code

struct Hash{
    int head[maxm], cnt, mod;
    struct Node{
        int v, id, next;
    }node[maxn];
    void init(){
        mes(head, -1);
        cnt = 0;
        mod = 1333331;
    }
    void insert(int x, int id){
        int u = x%mod;
        node[++cnt].v = x;
        node[cnt].id = id;
        node[cnt].next = head[u];
        head[u] = cnt;
    }
    int find(int x){
        int u = x%mod;
        for(int i = head[u]; ~i; i = node[i].next){
            if(node[i].v == x)
                return node[i].id;
        }
        return -1;
    }
}hs;
  
ll qpow(ll a, ll b, int mod){
    ll ans = 1;
    while(b){
        if(b&1)
            ans = ans*a%mod;
        a = a*a%mod;
        b /= 2;
    }
    return ans;
}
struct BSGS{
    int bm, gm, a, b, x0, p;
      
    void init(){
        bm = (int)ceil(pow(p, 2.0/3));
        gm = (int)ceil(pow(p, 1.0/3));
        ll ans = 1;
        hs.init();
        for(int i = 0; i <= bm; i++){   //a^(i*bm - j)%p = b;
            hs.insert(ans, i);
            ans = ans*a%p;
        }
    }
  
    ll get(ll v){     
        v = qpow(v, p-2, p);
        ll num = qpow(a, bm, p);
        for(int i = 1; i <= gm; i++){
            v = v*num%p;
            int ans = hs.find(v);
            if(ans != -1)
                return 1ll*i*bm - ans;
        }
        return -1;
    }
}bsgs;
 

example

Cattle off more school training camp fifth - generator 2

\ (x_n = (A * X_ {n--. 1} + B) \% P \) , you \ (n-, x_0, A, B, P \) , \ (Q \) th ask \ (x_0, x_1, x_2 ..., x_ {n -1} \) finding the minimum compliance \ (x_i = v \) a \ (I \) , the output is not present \ (- 1 \) .

Thinking

\ [x_n = A * X_ {n--. 1} + B \] \ [x_n = A ^ n-* x_0 + B * \ FRAC {. 1-A ^ n-} {. 1-A} \] \ [A ^ n-= \ FRAC {(A-. 1) _ * x_n + B} {(A-. 1) * x_0 + B} \] \ [x_n = V, so that B = \ frac {(a- 1) _ * v + b} {(a-1) * x_0 + b} \] it is seeking \ [^ n-a \ B equiv \ PMOD P \]
\ (a = 0, a =. 1 \) case to consider the special

AC Code

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>
  
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e6 + 10;
const int    maxm = 2e6 + 10;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;
  
int n, m;
int cas, tol, T;
struct Hash{
    int head[maxm], cnt, mod;
    struct Node{
        int v, id, next;
    }node[maxn];
    void init(){
        mes(head, -1);
        cnt = 0;
        mod = 1333331;
    }
    void insert(int x, int id){
        int u = x%mod;
        node[++cnt].v = x;
        node[cnt].id = id;
        node[cnt].next = head[u];
        head[u] = cnt;
    }
    int find(int x){
        int u = x%mod;
        for(int i = head[u]; ~i; i = node[i].next){
            if(node[i].v == x)
                return node[i].id;
        }
        return -1;
    }
}hs;
  
ll qpow(ll a, ll b, int mod){
    ll ans = 1;
    while(b){
        if(b&1)
            ans = ans*a%mod;
        a = a*a%mod;
        b /= 2;
    }
    return ans;
}
struct BSGS{
    int bm, gm, a, b, x0, p;
      
    void init(){
        bm = (int)ceil(pow(p, 2.0/3));
        gm = (int)ceil(pow(p, 1.0/3));
        ll ans = 1;
        hs.init();
        for(int i = 0; i <= bm; i++){   //a^(i*bm - j)%p = b;
            hs.insert(ans, i);
            ans = ans*a%p;
        }
    }
  
    ll get(ll v){     
        v = qpow(v, p-2, p);
        ll num = qpow(a, bm, p);
        for(int i = 1; i <= gm; i++){
            v = v*num%p;
            int ans = hs.find(v);
            if(ans != -1)
                return 1ll*i*bm - ans;
        }
        return -1;
    }
}bsgs;
  
  
int main() {
    scanf("%d", &T);
    while(T--){
        ll n,x0, a, b, p;
        scanf("%lld%lld%lld%lld%lld", &n, &x0, &a, &b, &p);
        bsgs.x0 = x0; bsgs.a = a; bsgs.b = b; bsgs.p = p;
        bsgs.init();
        int q;ll v;
        scanf("%d", &q);
        ll inv = ((a-1)*x0%p+b+p)%p;
        if(inv == 0){
            while(q--){
                scanf("%lld", &v);
                if(x0 == v)
                    printf("0\n");
                else
                    printf("-1\n");
            }
            continue;
        }
        if(a == 0){
            while(q--){
                scanf("%lld", &v);
                if(v == x0)         //x = x0;
                    printf("0\n");
                else if(v == b) //xn = b
                    printf("1\n");
                else
                    printf("-1\n"); //无解
                continue;
            }
            continue;
        }
        if(a == 1){   //xn = x0 + nb;
            ll invb = qpow(b, p-2,p);
            while(q--){
                scanf("%lld", &v);
                if(b == 0){  
                    if(v == x0)
                        printf("0\n");
                    else
                        printf("-1\n");
                }
                else{   // n = (v - x0)/b;
                    ll ans = ((v-x0+p) % p * invb%p + p)%p;
                    if(ans < n)
                        printf("%lld\n", ans);
                    else
                        printf("-1\n");
                }
            }
            continue;
        }
        inv = qpow(inv, p-2, p);
        while(q--){
            scanf("%lld", &v);
            v = ((a-1)*v%p+b+p)%p*inv%p;
            ll ans = bsgs.get(v);
            if(ans == -1 || ans >= n)
                printf("-1\n");
            else
                printf("%lld\n", ans);
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/zhuyou/p/11404644.html