解 xq≡p(modp) 其中 q⊥p.如果知道了 at≡a(modp),那么 x=at/q,想要让 t 是 q 的倍数,现在已经有了 ap−1≡1(modp),那么就有 a(p−1)t+1≡a(modp),由于 k⊥(p−1),所以一定有这样一个 t,那么 x=a(p−1)t+1q=a1q(注意指数是在 mod(p−1) 意义下的)
现在想求 k 的二次剩余,x2=a(modp),假如我们知道 at≡1(modp) 其中 t 是奇数,那么 x=at+12.
现在有 ap−1≡1(modp),如果将 p−1 分解为 2Kt,我们想要不断除掉 2,最终得到 t.
如果现在 a2k−1t≡−1(modp) 了,现在想要凑一个新的 a′,使得 a′2k−1t=1 并且解出来的 x′ 能够得到 x.那么这里就考虑一个 v2=−1,那么 (v2a)2k−1t=1,那么 x=x′/v.
然后考虑任意一个无二次剩余的 w 其满足 w(p−1)/2=−1=w2K−1t=(w2K−k)2k−1t,所以这里就知道想要的是 w2K−k−1.
注记:Euler 判定:ap−12 为 1 则存在二次剩余,为 −1 则不存在二次剩余。这同时也告诉我们 check 失败时候的 k 一定 <K,这也是最后一步中 K−k−1≥0 从而 w2K−k−1 能算的原因。
处理细节:
- 求 w 可以不断随机然后用 Euler 判定(二次剩余数量和二次非剩余数量相同)。
- 不断平方预处理出 at,a2t,a4t,⋯a2Kt,以及 w1,w2,w4⋯,w2K.
127 说的好,当我们想要记住一个算法过程时,可以去记算法过程中的关键步骤,中间的直接推就好了,现在尝试提炼出这个算法的思路:
- at≡1(modp)⇒x=at+12;
- 从 a(p−1)≡1(modp) 开始不断尝试将指数除以 2 来得到一个奇数 t,但是不断开根的过程中可能从 1 变成 -1,此是要凑出一个 a′ 满足 a′2k−1t≡1(modp) 并且其截出的 x′ 能简单得得到 x;
- a′=v2a,欲求 v2≡−1(modp),利用二次非剩余 wp−12≡−1(modp) 并将指数分解,来凑出满足条件的 v.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?