浅谈BSGS(大步小步)

用途:

一般用来求\(a^x\equiv b\,\,(mod\,p)\)的最小正整数解,其中gcd(a,p)=1

\(u=\lceil sqrt(p)\rceil\),则式子可以转化为\(a^{iu-j}\equiv b\,\,(mod\,p)\),其中\(i\in[1,u],j\in[0,u)\)

于是\(a^{iu}\equiv a^jb\,\,(mod\,p)\),我们就可以枚举j,存到map中,再枚举i判重就行了

不过当存在不同的j使\(a^jb\,mod\,p\)相同时,我们记录较大的(因为j越大答案越小嘛)

简易原理:

费马小定理:若gcd(x,p)=1,则有\(\\x^{p-1}\equiv1\,\,(mod\,p)\),得到\(x^p\equiv x\,\,(mod\,p)\)

所以当指数不小于p时,mod p的值会形成循环

Code:

板子题:luogu P4028 New Product

#include<bits/stdc++.h>
#define ll long long
using namespace std;
map<int,int> mp;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int quickpow(int a,int b,int p){
    int re=1;
    while(b){if(b&1) re=1ll*re*a%p;a=1ll*a*a%p;b>>=1;}
    return re;
}
void solve(){
    int p=read(),a=read(),b=read();
    if(a%p==0){puts("Couldn't Produce!");return ;}
    if(b==1){puts("0");return ;}
    int u=sqrt(p)+1,v=b;mp.clear();
    for(int i=0;i<u;i++)
        mp[v]=i,v=1ll*v*a%p;
    int w=quickpow(a,u,p);v=1;
    for(int i=1;i<=u;i++){v=1ll*v*w%p;
        if(mp.count(v)){
            printf("%d\n",i*u-mp[v]);
            return ;
        }
    }puts("Couldn't Produce!");
}
int main(){
    int T=read();
    while(T--) solve();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/NLDQY/p/10877282.html
今日推荐