[BZOJ1467]Pku3243 clever Y(扩展BSGS)

题目描述

传送门

题解

[BZOJ1467]Pku3243 clever Y(扩展BSGS)_第1张图片

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
#define LL long long

LL A,B,P;
map <LL,bool>has_been;
map <LL,LL>hash;

inline LL gcd(LL a,LL b){if (!b) return a; else return gcd(b,a%b);}
inline LL fast_pow(LL A,LL m,LL P){
    LL ans=1;
    for (;m;m>>=1,A=A*A%P)
      if (m&1)
        ans=ans*A%P;
    return ans;
}
inline LL Exbsgs(LL A,LL B,LL P){
    A%=P,B%=P; if (B==1) return 0;
    LL t=1,d=1,k=0;
    while ((t=gcd(A,P))!=1){
        if (B%t) return -1;
        k++,B/=t,P/=t,d=d*(A/t)%P;
        if (B==d) return k;
    }
    hash.clear(); has_been.clear();
    LL m=ceil(sqrt(P)); LL A_m=fast_pow(A,m,P);
    LL mul=B; hash[mul]=0; has_been[mul]=true;
    for (LL j=1;j<=m;++j) {mul=mul*A%P;hash[mul]=j;has_been[mul]=true;}
    for (LL i=1;i<=m;++i) {d=d*A_m%P;if (has_been[d]) return i*m-hash[d]+k;}
    return -1;
}
int main(){
    while (~scanf("%lld%lld%lld",&A,&P,&B)){
        if (!A&&!P&&!B) return 0;
        LL ans=Exbsgs(A,B,P);
        if (ans!=-1) printf("%lld\n",ans); else printf("No Solution\n");
    }
}

总结

抽空学一下手写hash

你可能感兴趣的:(数论,poj,bzoj)