SGU 261 Discrete Roots(原根+BabyStepGiantStep)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=261

题意:给定P,K,A。P为素数,0<=A<=P-1.求满足x^K%P=A的所有解x。(0<=x<=P-1)。

思路:首先求出P的原根g,即g^(P-1)%P=1。设x=g^i,A=g^j,那么就是求ki=j(%P-1)的i。

 
   




i64 P,K,A;

vector<i64> fac;



void init()

{

    i64 i,n=P-1;

    for(i=2;i*i<=n;i++) if(n%i==0)

    {

        fac.pb(i);

        while(n%i==0) n/=i;

    }

    if(n>1) fac.pb(n);

}



i64 power(i64 a,i64 b)

{

    i64 ans=1;

    while(b)

    {

        if(b&1) ans=ans*a%P;

        a=a*a%P;

        b>>=1;

    }

    return ans;

}



int isPrimitiveRoot(i64 a)

{

    int i;

    for(i=0;i<SZ(fac);i++)

    {

        if(power(a,(P-1)/fac[i])==1) return 0;

    }

    return 1;

}



i64 findRoot()

{

    i64 i;

    for(i=2;i<P;i++)

    {

        if(isPrimitiveRoot(i)) return i;

    }

    return -1;

}



i64 exGcd(i64 a,i64 b,i64 &x,i64 &y)

{

    if(!b)

    {

        x=1;

        y=0;

        return a;

    }

    i64 r=exGcd(b,a%b,x,y);

    i64 t=x;

    x=y;

    y=t-a/b*y;

    return r;

}



i64 reverse(i64 a,i64 b)

{

    i64 x,y;

    exGcd(a,b,x,y);

    x=(x%b+b)%b;

    return x;

}



i64 babyStepGiantStep(i64 root,i64 A,i64 P)

{

    i64 m=sqrt(1.0*P)+3,e=1,c=power(root,m),i;

    map<i64,i64> H;

    FOR0(i,m)

    {

        if(!H[e]) H[e]=i;

        e=e*root%P;

    }

    e=A;

    for(i=0;i<=m;i++)

    {

        if(H[e]) return i*m+H[e];

        e=A*reverse(power(c,i+1),P)%P;

    }

    return -1;

}



int main()

{

    RD(P,K,A);

    if(P==2)

    {

        puts("1");

        PR(A);

        return 0;

    }

    if(A==0)

    {

        puts("1");

        puts("0");

        return 0;

    }

    init();

    i64 g=findRoot();

    i64 j=babyStepGiantStep(g,A,P);

    if(j==-1)

    {

        puts("0");

        return 0;

    }

    i64 x,y,d=exGcd(K,P-1,x,y);

    if(j%d)

    {

        puts("0");

        return 0;

    }

    x=x*j/d;

    d=(P-1)/d;

    while(x<0) x+=d;

    set<i64> s;

    set<i64>::iterator it;

    y=power(g,x);

    while(s.find(y)==s.end())

    {

        s.insert(y);

        x+=d;

        y=power(g,x);

    }

    PR(SZ(s));

    for(it=s.begin();it!=s.end();it++) PR(*it);

    return 0;

}

 
   

  

 
  

你可能感兴趣的:(root)