您的位置:首页 > 其它

二次剩余Cipolla算法学习小记

2016-07-20 21:59 169 查看

Preface

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

详细的解释见维基百科

Paper

首先我们要弄清楚什么叫二次剩余,其实就是对于给定的p(p∈P)和n,如果有x满足x2≡n(modp),那么n在模p意义下就是二次剩余。说白了就是模意义下能否开根号。

我们只讨论p为奇素数的情况。

我们先定义Fp,这是一个数域,其实就是0到p−1这p个数与模p意义下加减乘除运算构成的集合。

定理1:对于x2≡n(modp),总共有p−12个的n能使该方程有解(将n=0情况除去,由于该情况显然有x=0)。

证明:我们只用考虑所有x2。如果存在不同的两个数u、v,它们的平方在模p意义下同余,那么显然有p|(u2−v2)。由平方差公式p|(u+v)(u−v)。显然p不可能整除u−v,因此p整除u+v,因此u+v≡0(modp)。这个结论反过来也是成立的,因此共有p−12种互不相同的平方,显然对应了所有有解的n,而且同一个n还一定存在两个互为相反数的解。

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

它是这样定义的

(ap)=⎧⎩⎨1,−1,0,a在模p意义下是二次剩余a在模p意义下是非二次剩余a≡0(modp)

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

定理2:(ap)≡ap−12(modp)

证明:

当a在模p意义下是二次剩余时,令x2≡a(modp),那么就有xp−1≡1(modp),由费马小定理,显然x存在。

当a在模p意义下不是二次剩余时,依旧令x2≡a(modp),那么就有xp−1≡−1(modp),由费马小定理,显然x不存在。

当a≡0(modp)时显然满足。

那么我们就可以通过快速幂计算勒让德符号来判定一个数在模p意义下是否是二次剩余了。

有了这些理论基础,我们可以开始算法了。

首先我们要明确我们要求x2≡n(modp)的解x(假定n在模p意义下是二次剩余,由定理1有两个互为相反数的可行解)。

算法一开始的时候我们首先要通过不断地随机(你没有听错,就是随机)出一个数a,使得(a2−np)为−1,也就是不能开根号。先不要管为什么是a2−n,我们来算算随机次数的期望。还是由定理1,一共有p−12个数满足勒让德记号值为−1,因此一次随机得到结果的概率为p−12p。当p够大的时候,这个概率是趋近于12的。那么列一下期望的树状图,就可以得到期望次数为2。

那么我们得到这个不能开根号的数之后要干什么呢?我们要干一件丧心病狂的事情,那个数不能开根号,我们非要给它一个域Fp2让它可以开根号(类比−1−−−√所在的复数域)。我们将a2−n−−−−−√定义为这个域的“虚数单位元”(类比i=−1−−−√),设它为ω,那么这个“复数域”Fp2的数就一定可以表达为a+bω(类比复数域a+bi,bω相当于虚部)。

那么我们将复数域的四则运算法则全部类比到Fp2上面,显然它依然满足封闭性、交换律、结合律以及分配律的,还存在加法零元和乘法逆元(貌似符合环的定义)。具体看下图。



那么它就是一个合法的数域。

然后我们定义这个数域有什么用呢?

x≡(a+ω)p+12(modp)

啊?就这么简单???

我们首先来证明一些东西:

定理3:ωp≡−ω(modp)

证明:ωp≡ω×ωp−1≡ω×(ω2)p−12≡ω×(a2−n)p−12≡−ω(modp)

定理4:(a+b)n≡an+bn(modn)(n∈P)

证明:使用二项式定理我们能得到(a+b)n≡∑i=0nCinaibn−i(modn)由于n是质数,因此当i不等于0且不等于n的时候,组合数阶乘公式中的n是没有办法被消掉的,就会被模成0,因此这些项都是对答案没有贡献的。而i=0或i=n时,我们就分别可以得到an和bn,定理得证。

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

x2≡(a+ω)p+1≡(a+ω)p(a+ω)≡(ap+ωp)(a+ω)≡(a−ω)(a+ω)(注意a是满足费马小定理的,即ap−1≡1(modp))≡a2−ω2≡a2−(a2−n)≡n(modp)

然后x取相反数也是一个解。这时可能有人会问,我们得到的解会在Fp2域上的,但是我们要求的是Fp域的解,也就是说我们所谓的“虚部”ω系数是否可能不为0。

其实我们不需要担心这个问题,由拉格朗日定理,我们知道在任意一个模p(p∈P)的数域里面,任意一个多项式f(x)最多有deg(f(x))个根(f(x)≡0(modp)的解称为f(x)在Fp下的根),deg表示多项式的度数,即最大指数。由于Fp2是对Fp域的扩充,Fp域的两根一定在Fp2内也有效,并且我们知道x2−n在数域Fp2下的根有两个(x1,x2),那么x1,x2一定也是Fp域下的根,也就是“虚部”系数为0。

由此问题完美解决,算法时间复杂度貌似是O(log2p)的。

Code

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

Problems

二次剩余的题目应该不怎么多。这个我会在博客里慢慢更新吧。

z给我们讲了CodeChef上面一道丧心病狂的BSGS(离散对数)和Cipolla(二次剩余)连用的题目FN
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: