BSGS算法

BSGS算法

AxB(%C) 已知A、B、C 求x

题意应该很好理解。

设x=i*m-j 这样就有A(i*m-j)B(%C)  Aj*BA(i*m)(%C)

枚举j,范围0~m 将Aj*B的值存下来

枚举i,范围1~m 第一个满足Aj×B=A(m*i) (mod C)时的i*m-j即为所求。

当然此时有可能是负值,所以记得特殊处理一下,

 

还要一个问题没有解决,m的值如何确定?

ceil(C)是m的上限,为什么?

费马小定理:a(p-1)1(%p) p是质数,a,p互质,这里的p就相当于本题中的C

同时很容易得到a(k mod p-1)ak(mod p)的公式

 

k mod p-1就是k-m(p-1),原式就变成了ak-m(p-1)ak(mod p),即ak/am(p-1)≡ak (mod p) 

得到:am(p-1)≡1(mod p)。所以 a(k mod p-1)ak(mod p

 

所以:如果枚举x的话枚举到p即可。

 

所以使imj<=p,即m=ceil(C),i,j最大值也为m。

 

省选有02,用map相当方便

 

#include<cstdio>
#include<map>
#include<cmath>
using namespace std;
int a,b,c;
map<long long,int>mp; 
long long ksm(long long p)
{
    long long t=1,s=a;
    while(p)
    {
        if(p&1) t=(t*s)%c;
        p>>=1;
        s=s*s%c;
    }
    return t;
}
int main()
{
    scanf("%d %d %d",&a,&b,&c);
    int m=ceil(sqrt(c)),t=b%c,ans;
    mp[t]=0;
    for(int i=1;i<=m;i++)
    {
        t=(t*a)%c;
        mp[t]=i;
    }
    int x=ksm(m);
    t=1;
    for(int i=1;i<=m;i++)
    {
        t=(t*x)%c;
        if(mp[t])
        {
            ans=i*m-mp[t];
            printf("%d",(ans%c+c)%c);
            break;
        }
    }
    return 0;
}

 

posted @ 2018-01-17 14:59  Excim  阅读(128)  评论(0编辑  收藏  举报