题目描述
你被要求设计一个计算器完成以下三项任务:
- 给定 \(y,z,p\),计算 \(y^z \bmod p\) 的值;
- 给定 \(y,z,p\),计算满足 \(xy \equiv z \pmod p\) 的最小非负整数 \(x\);
- 给定 \(y,z,p\),计算满足 \(y^x \equiv z \pmod p\) 的最小非负整数 \(x\)。
为了拿到奖品,全力以赴吧!
Analysis
模板大融合...
第一问就是一个快速幂,第二问就是线性同余方程比较基础的东西这里就不再赘述。
我们主要来看第三问怎么做(其实就是bsgs的模板)。
根据费马小定理有\(y^{p-1} \equiv 1 \pmod p\),所以这东西是有循环节的。所以只要O(p-1)扫一遍判断就行
这里介绍一种更高效的算法:Baby-Step-Giant-Step(北上广深大步小步算法),可以优化到\(O(\sqrt{p})\)。
看到这个复杂度可能不少对分块熟悉的同学已经可以yy出做法了,其实bsgs就是用分块的思想。
先取一个\(t\),可得\(x=qt+r, 0 \le r \le t-1\),得到\(y^{qt+r} \equiv z \pmod p\),这样写不舒服,换一种写法:\(y^{(q+1)t - r'} \equiv z \pmod p\),即\(y^{(q+1)t} \equiv z \times y^{r'} \mod p\)。
先预处理出所有\(b \times y^{r'}\),当然尽量取更大的\(r'\)然后枚举\(q\)即可。显然\(t=\sqrt{n}\)时最好。
下面给出这道题的代码,注意部分特判:
#include
#include
#include
#include