spoj3105 BSGS拓展版+离散对数

来源:互联网 发布:python thinter视频 编辑:程序博客网 时间:2024/06/07 17:46

题目大意:求使得axb(modp)成立的最小自然数b
思路:任意一个 ax=abp+c 然后算出后面的值,枚举并在hash表中查询,如果p不是质数 p/=g;b/=g;t=t*(a/g)%p;
x=x`+1
Code:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<map>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long ll;ll a,b,p;ll gcd(int a,int b) {return b==0?a:gcd(b,a%b);}ll qpow(ll a,ll b,ll mod){    ll ret=1;    for(ll i=b;i;i>>=1,a=(a*a)%mod) {        if(i&1) ret*=a,ret%=mod;     }    return ret;}   ll BSGS(){    a%=p;b%=p;    if(b==1) return 0;    ll cnt=0,t=1;    for(ll g=gcd(a,p);g!=1;g=gcd(a,p)) {        if(b%g) return -1;        p/=g;b/=g;t=t*(a/g)%p; cnt++;        if(t==b) return cnt;     }    map<int,int>hash;    ll m=ll(sqrt(1.0*p)+1),    base=qpow(a,m,p),now=t,tmp=b;    for(int i=0;i<m;i++,tmp=(tmp*a)%p) {        hash[tmp]=i;    }    for(int i=1;i<=m+1;i++) {        now=now*base%p;        if(hash.count(now)) {            return i*m-hash[now]+cnt;        }     }    return -1;}int main(){    while(scanf("%lld%lld%lld",&a,&p,&b)) {        if(a==b&&b==p&&a==0) break;        ll ans=BSGS();        ans==-1?puts("No Solution"):printf("%lld\n",ans);    }    return 0;}
原创粉丝点击