二次剩余Cipolla算法学习小记

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a_crazy_czy/article/details/51959546

Preface

今天z大神给我们讲数论和代数,然后后面讲了几个超级神的算法。Cipolla算是其中一个吧。貌似国内直接查名字还没有什么资料,查二次剩余的算法有ACdreamer简略的介绍。今天听讲时算是听懂了大半,回来又搞鼓了整个晚上才算完全弄明白。这个算法真的是从头到尾都是脑洞,太神了!
详细的解释见维基百科


Paper

首先我们要弄清楚什么叫二次剩余,其实就是对于给定的p(pP)n,如果有x满足x2n(modp),那么n在模p意义下就是二次剩余。说白了就是模意义下能否开根号。
我们只讨论p为奇素数的情况。
我们先定义Fp,这是一个数域,其实就是0p1p个数与模p意义下加减乘除运算构成的集合。

  • 定理1:对于x2n(modp),总共有p12个的n能使该方程有解(将n=0情况除去,由于该情况显然有x=0)。
  • 证明:我们只用考虑所有x2。如果存在不同的两个数uv,它们的平方在模p意义下同余,那么显然有p|(u2v2)。由平方差公式p|(u+v)(uv)。显然p不可能整除uv,因此p整除u+v,因此u+v0(modp)。这个结论反过来也是成立的,因此共有p12种互不相同的平方,显然对应了所有有解的n,而且同一个n还一定存在两个互为相反数的解。

然后我们还要知道一个神奇的东西叫做勒让德符号(Legendre symbol)
它是这样定义的

(ap)=1,1,0,apapa0(modp)

那我们怎么求该符号的值呢?

  • 定理2:(ap)ap12(modp)
  • 证明:
    • a在模p意义下是二次剩余时,令x2a(modp),那么就有xp11(modp),由费马小定理,显然x存在。
    • a在模p意义下不是二次剩余时,依旧令x2a(modp),那么就有xp11(modp),由费马小定理,显然x不存在。
    • a0(modp)时显然满足。

那么我们就可以通过快速幂计算勒让德符号来判定一个数在模p意义下是否是二次剩余了。
有了这些理论基础,我们可以开始算法了。
首先我们要明确我们要求x2n(modp)的解x(假定n在模p意义下是二次剩余,由定理1有两个互为相反数的可行解)。
算法一开始的时候我们首先要通过不断地随机(你没有听错,就是随机)出一个数a,使得(a2np)1,也就是不能开根号。先不要管为什么是a2n,我们来算算随机次数的期望。还是由定理1,一共有p12个数满足勒让德记号值为1,因此一次随机得到结果的概率为p12p。当p够大的时候,这个概率是趋近于12的。那么列一下期望的树状图,就可以得到期望次数为2
那么我们得到这个不能开根号的数之后要干什么呢?我们要干一件丧心病狂的事情,那个数不能开根号,我们非要给它一个域Fp2让它可以开根号(类比1所在的复数域)。我们将a2n定义为这个域的“虚数单位元”(类比i=1),设它为ω,那么这个“复数域”Fp2的数就一定可以表达为a+bω(类比复数域a+bibω相当于虚部)。
那么我们将复数域的四则运算法则全部类比到Fp2上面,显然它依然满足封闭性、交换律、结合律以及分配律的,还存在加法零元和乘法逆元(貌似符合环的定义)。具体看下图。
证明
那么它就是一个合法的数域。
然后我们定义这个数域有什么用呢?
x(a+ω)p+12(modp)
啊?就这么简单???
我们首先来证明一些东西:

  • 定理3:ωpω(modp)
  • 证明:ωpω×ωp1ω×(ω2)p12ω×(a2n)p12ω(modp)
  • 定理4:(a+b)nan+bn(modn)(nP)
  • 证明:使用二项式定理我们能得到
    (a+b)ni=0nCinaibni(modn)
    由于n是质数,因此当i不等于0且不等于n的时候,组合数阶乘公式中的n是没有办法被消掉的,就会被模成0,因此这些项都是对答案没有贡献的。而i=0i=n时,我们就分别可以得到anbn,定理得证。

有了这些定理,我们就可以嘿嘿嘿。

x2(a+ω)p+1(a+ω)p(a+ω)(ap+ωp)(a+ω)(aω)(a+ω)aap11(modp)a2ω2a2(a2n)n(modp)

然后x取相反数也是一个解。这时可能有人会问,我们得到的解会在Fp2域上的,但是我们要求的是Fp域的解,也就是说我们所谓的“虚部”ω系数是否可能不为0
其实我们不需要担心这个问题,由拉格朗日定理,我们知道在任意一个模p(pP)的数域里面,任意一个多项式f(x)最多有deg(f(x))个根(f(x)0(modp)的解称为f(x)Fp下的根),deg表示多项式的度数,即最大指数。由于Fp2是对Fp域的扩充,Fp域的两根一定在Fp2内也有效,并且我们知道x2n在数域Fp2下的根有两个(x1,x2),那么x1,x2一定也是Fp域下的根,也就是“虚部”系数为0
由此问题完美解决,算法时间复杂度貌似是O(log2p)的。


Code

我目前还没有去实现这个算法,我实现了会在这里贴上。


Problems

二次剩余的题目应该不怎么多。这个我会在博客里慢慢更新吧。
z给我们讲了CodeChef上面一道丧心病狂的BSGS(离散对数)和Cipolla(二次剩余)连用的题目FN

展开阅读全文

没有更多推荐了,返回首页