Baby-step giant-step  解高次同余方程a^x=b(mod n) 模版

思路
说一下a^x=b(mod n)的Baby Step Giant Step算法(一点分块的思想)

m取sqrt(p);
求y^x=z(mod p)设x=km+i
y^km∗y^i≡z
yi≡z∗ine(y^km)(逆元)
用费马小定理

y^(p-1)mod p=1;
y^m * y^(p-m-1) mod p =1;
y^m的逆元为y^(p-m-1)

ine(y^m)≡y^(p−1−m)
设其为T
ine(y^km)≡ine(y^(k−1)m)∗T
把y^i(0<=i<=m)放入map;
然后枚举k,查询
z∗ine(y^km)

描述:Theory

The algorithm is based on a space-time tradeoff. It is a fairly simple modification of trial multiplication, the naive method of finding discrete logarithms.

Given a cyclic group G of order n, a generator \alpha of the group and a group element \beta, the problem is to find an integer x such that

\alpha^x = \beta\,.

The baby-step giant-step algorithm is based on rewriting x as x = im + j, with m = \left\lceil \sqrt{n} \right\rceil and 0 \leq i < m and 0 \leq j < m. Therefore, we have:

\beta(\alpha^{-m})^i=\alpha^j\,.

The algorithm precomputes \alpha^j for several values of j. Then it fixes an m and tries values of i in the left-hand side of the congruence above, in the manner of trial multiplication. It tests to see if the congruence is satisfied for any value of j, using the precomputed values of \alpha^j.
The algorithm

Input: A cyclic group G of order n, having a generator α and an element β.

Output: A value x satisfying \alpha^{x}=\beta.

m ← Ceiling(√n)
For all j where 0 ≤ j < m:
    Compute αj and store the pair (j, αj) in a table. (See section "In practice")
Compute α−m.
γ ← β. (set γ = β)
For i = 0 to (m − 1):
    Check to see if γ is the second component (αj) of any pair in the table.
    If so, return im + j.
    If not, γ ← γ • α−m.

代码

long long cheng(long long a,long long b,long long p)
{
    long long ans=1;
    while(b>0)
    {
        if(b&1) ans=ans*a%p;
        a=a*a%p;
        b>>=1;
    }
    return ans;
}
void solve3()
{
    while(T--)
    {
        flag=0;
        long long x,y;
        long long d;
        scanf("%lld%lld%lld",&aa,&bb,&p);

        aa%=p;
        if(!aa&&!bb)    
        {
            printf("1\n");
            continue;
        }
        if(!aa)
        {
            printf("Orz, I cannot find x!\n");
            continue;
        }
        mp.clear();
        long long m=ceil(sqrt(p)),t=1;
        mp[1]=m+1;
        for(long long i=1;i<m;i++) 
        {
            t=t*aa%p;
            if(!mp[t]) mp[t]=i;
        }
        long long tmp=cheng(aa,p-m-1,p),ine=1;
        for(long long k=0;k<m;k++)
        {
            int i=mp[bb*ine%p];
            if(i)
            {   
                flag=1;     
                if(i==m+1) i=0;
                printf("%lld\n",k*m+i);
                break;
            }
            ine=ine*tmp%p;
        }
        if(!flag)
        printf("Orz, I cannot find x!\n");
    }       
}

附,一个例题:【bzoj2242】[SDOI2011]计算器
http://blog.csdn.net/ALPS233/article/details/51148958

你可能感兴趣的:(C语言)