标签:
先看一个式子
现在只知道x和z,要求y。
大步小步算法(BSGS,Baby Steps Giant Steps)就是解决这个问题。
根据费马小定理:
如果y已经枚举到了z-1了,继续枚举的话就会产生循环。
所以,在暴搜中y的枚举范围就是0……z-1。
我们想一想可不可以用分块来解决枚举的y。
把y分成
设m=
那么现在就变成了
把a和b分别放在两边:
我们可以发现左边的
ll m=ceil(sqrt(p-1));
ll ni=qsm(x,m);ni=qsm(ni,p-2);//因为右边的指数是复数,所以需要逆元
a.clear();
a[1]=m+1;
fo(j,1,m-1){
k=k*x%p;
if(!a[k])a[k]=j;
}
然后枚举右边的a就好了。
fo(i,0,m-1){
ll u=a[y];
if(u){
if(u==m+1)printf("%lld\n",i*m);
else printf("%lld\n",i*m+u);
return;
}
y=y*ni%p;
}
printf("Orz, I cannot find x!\n");
这就是
很优美的暴搜。
经典的裸题SDOI2011 计算器
对于BSGS算法知道的,也只有这么多了。
标签:
原文地址:http://blog.csdn.net/doyouseeman/article/details/52084773