二次剩余

ppp是奇素数。所有的运算都是在群Zp∗Z_{p}^{*}Zp∗​中的运算。方程x2=a≠0x^2=a \neq 0x2=a̸​=0问是否有解,以及解是什么?若有解,aaa就是模ppp的二次剩余;若无解,则aaa就是模ppp的非二次剩余。

  1. a=0a=0a=0,显然只有唯一解x=0x=0x=0.

  2. a≠0a\neq 0a̸​=0,有解等价于ap−12=1a^{\frac{p-1}{2}}=1a2p−1​=1;无解等价于ap−12=−1a^{\frac{p-1}{2}}=-1a2p−1​=−1.

群Zp∗Z_{p}^{*}Zp∗​恰好有一半的元素是二次剩余,一半的元素不是二次剩余。当元素aaa是二次剩余是,解有且只有两个x0,x1x_0,x_1x0​,x1​,且x0=−x1x_0=-x_1x0​=−x1​,即解x=±cx=\pm cx=±c

因此,验证aaa是否是二次剩余可以用快速模幂,复杂度O(log⁡2p)O(\log_2{p})O(log2​p).

对于二次剩余aaa,求解x使用[Cipolla]{.underline}(洋葱? 奇波拉?)算法。

Cipolla(洋葱?)算法

这是一个随机性算法,复杂度是O(log⁡2p)O(\log_2{p})O(log2​p)

这个算法是在域Fp2F_{p^2}Fp2​上进行运算的,在这个域上做乘法、幂运算,然后解的那个表达式算出来之后,一定是属于域FpF_{p}Fp​的,Fp2F_{p^2}Fp2​是FpF_{p}Fp​的扩充。

  1. 使用随机的方法,找到一个满足bbb满足b2−ab^2-ab2−a不是二次剩余。需要检验b2−ab^2-ab2−a是不是二次剩余的期望次数是222.每次检验是O(log⁡2p)O(\log_2{p})O(log2​p).

  2. 定义域Fp2F_{p^2}Fp2​上的*“虚部单位”*为ω\omegaω,其中Fp2=a+bω∣a,b∈FpF_{p^2}={a+b\omega| a,b \in F_p}Fp2​=a+bω∣a,b∈Fp​,且ω2=b2−a\omega^2=b^2-aω2=b2−a.

  3. x2=ax^2=ax2=a的其中一个**解是x=(b+ω)p+12.x=(b+\omega)^{\frac{p+1}{2}}.x=(b+ω)2p+1​.*注意,虽然运算是Fp2F_{p^2}Fp2​上的,但是右边的那个式子算出来的结果刚好是"虚部"*为0的元素。原因是x2=a(x∈Fp)x^2=a \quad (x \in F_p)x2=a(x∈Fp​)与x2=(xa+xbω)2=a+0ω(x∈Fp2,xa,xb∈Fp)x^2=(x_a+x_b\omega)^2=a+0\omega \quad (x \in F_{p^2},x_a,x_b \in F_p)x2=(xa​+xb​ω)2=a+0ω(x∈Fp2​,xa​,xb​∈Fp​)这两个方程都有且仅有两个解。而前面方程的解显然是后面两个方程的解,所以前面方程的解。所以前面这个方程和后面这个方程的解是完全一样的。而对于后面这个方程x=(b+ω)p+12x=(b+\omega)^{\frac{p+1}{2}}x=(b+ω)2p+1​代入后面的方程去验证(为了计算简洁,先证明了一些性质),会发现它的确是解,于是这个式子就是一开始方程的解。

证明

判别准则的证明

a≠0a\neq 0a̸​=0,有解等价于ap−12=1a^{\frac{p-1}{2}}=1a2p−1​=1;无解等价于ap−12=−1a^{\frac{p-1}{2}}=-1a2p−1​=−1.

以上这个命题的证明,主要分为——

这个的证明主要是需要用到Zp∗Z_p^*Zp∗​是个循环群,每个元素都可以表示成生成元的幂次的形式。

首先,明确一点,因为∀a∈Zp∗,ap−1=1\forall a \in Z_p^*,a^{p-1}=1∀a∈Zp∗​,ap−1=1,再运用根据二次探测定理,容易得到ap−12a^{\frac{p-1}{2}}a2p−1​取值只能是±1\pm1±1,即111或p−1p-1p−1.

  • 有解,即aaa是二次剩余,则ap−12a^{\frac{p-1}{2}}a2p−1​算出来是,这个将aaa换成x2x^2x2,再根据费马小定理易得。
  • 无解,即aaa不是二次剩余,容易推出aaa表示成生成元bbb的幂次的形式(bkb^kbk)中的kkk只能是奇数(否则,取x=bk2x=b^{\frac{k}{2}}x=b2k​就可以导出x2=ax^2=ax2=a)。将kkk表示成2u+12u+12u+1的形式,然后将a=b2u+1a=b^{2u+1}a=b2u+1代入ap−12a^{\frac{p-1}{2}}a2p−1​容易得到ap−12=bp−12a^{\frac{p-1}{2}}=b^{\frac{p-1}{2}}a2p−1​=b2p−1​.因为bbb是生成元,所以阶是p−1p-1p−1,指数小于p−1p-1p−1时,算出来都不是单位元111.所以bp−12=−1b^{\frac{p-1}{2}}=-1b2p−1​=−1(别忘了只能取±1\pm1±1).

    虽然以上每一点都只进行了单向推导,但是以上两点综合起来,就说明了“a≠0a\neq 0a̸​=0,有解等价于ap−12=1a^{\frac{p-1}{2}}=1a2p−1​=1;无解等价于ap−12=−1a^{\frac{p-1}{2}}=-1a2p−1​=−1.”

解的证明

算法构造的解,运算是在Fp2=x∣x=a+bω∧a,b∈FpF_{p^2}={x|x=a+b\omega \wedge a,b \in F_p}Fp2​=x∣x=a+bω∧a,b∈Fp​,其中ω2=b2−a\omega^2=b^2-aω2=b2−a.

对于&lt;Fp2,+,∗&gt;&lt;F_{p^2},+,*&gt;<Fp2​,+,∗>

并且定义了(a1+b1ω)+(a2+b2ω)=(a1+b1)+(b1+b2)ω(a_1+b_1\omega)+(a_2+b_2\omega)=(a_1+b_1)+(b_1+b_2)\omega(a1​+b1​ω)+(a2​+b2​ω)=(a1​+b1​)+(b1​+b2​)ω,

(a1+b1ω)×(a2+b2ω)=(a1b1+b1b2ω2)+(b1a2+a1b2)ω(a_1+b_1\omega) \times (a_2+b_2\omega)=(a_1b_1+b_1b_2\omega^2)+(b_1a_2+a_1b_2)\omega(a1​+b1​ω)×(a2​+b2​ω)=(a1​b1​+b1​b2​ω2)+(b1​a2​+a1​b2​)ω

定义完了之后,可以通过基本的代数知识,证明&lt;Fp2,+,∗&gt;&lt;F_{p^2},+,*&gt;<Fp2​,+,∗>是一个域。

原方程是在x2=ax^2=ax2=a在FpF_pFp​域内,而将方程的研究域改为Fp2F_{p^2}Fp2​之后。

无论是原域还是新域,解的个数至多只有两个。(这个是拉格朗日定理得出来的,暂时不懂朗格朗日定理,搁置,记结论)。因此,a是二次剩余的情况下,原方程有解x=±cx=\pm cx=±c,这两个解显然是新域下的解。又因为新域下没有更多解,所以新域下的解就是原域下的解。

因此,证明就只剩下验证x=(b+ω)p+12x=(b+\omega)^{\frac{p+1}{2}}x=(b+ω)2p+1​符合方程x2=ax^2=ax2=a即可。

直接代入计算就好了。只是由于为了计算比较简洁,有条理,不会算不下去,先给出了不少性质(定理)。这个别的博客基本都有,就不复言了。

下面为模板:

域Fp2F_{p^2}Fp2​乘法与幂运算模板

应当放在**mod_sys(见快速乘幂)**的模板前面。

	// 二次剩余模板,注意,各个函数都假设p^2即mod^2不会爆ll
// 域F_p的拓展域F_{p^2}
struct F_p2_node{ll a,b;}; // F_p2_node所有的运算都应该通过F_p2_sys来管理调用。
// 预设所有传入参数都是合法的。
struct F_p2_sys{
ll p,w2;
typedef F_p2_node nd;
nd mlt(const nd&x, const nd&y) const {
nd ans;
//(x.a+x.bw)(y.a+y.bw)
ans.a = (x.a*y.a%p+x.b*y.b%p*w2%p)%p;
ans.b = (x.b*y.a%p+x.a*y.b%p)%p;
return ans;
}
// pre n>=0 非递归版 不可改成引用!
nd pow(nd a, ll n) const {
if (n == 0) {return nd{1,0};}
// 始终维持要求的数可以表示为(a)^n*t
nd t{1,0};
while (n > 1)
{
if (n&1) t = mlt(t,a);
n >>= 1; a = mlt(a,a);
}
return mlt(t,a);
}
};

Cipolla洋葱算法实现模板

需要使用先用快速乘幂的模板中的mod_sys,实际上,这个模板只是给那个mod_sys增加了成员函数。

struct mod_sys{
// template code from 快速乘幂 见前面章节
some code.... // 预设a \not\equiv 0 (mod mod) 返回a是否是二次剩余
// 预设mod是奇素数
// 预设p^2不会爆long long,使用pow 若爆则改用pow_v2或者__int128
bool is_quadratic_residue(ll a) {
return 1 == pow(a,mod-1>>1);
} // 解方程x^2 = a (mod mod) p = mod 是奇质数
// 返回是否有解。如果有x0,x1(x0<=x1)存储解 仅解是0的时候取等号
// 洋葱算法。
// 预设p^2不会爆long long,使用pow 若爆则改用pow_v2或者__int128
bool sqrt(ll a,ll& x0, ll& x1) { // 需要一个随机数生成器
a = to_std(a);
if (a == 0) {x0 = x1 = 0; return true;}
if (!is_quadratic_residue(a)) return false;
uniform_int_distribution<> dis(1, mod-1);
ll b,w2;
while(true) {
b = dis(gen);
w2 = to_std((b*b)%mod-a);
if (!is_quadratic_residue(w2)) break;
}
// x = (b+w)^{(p+1)/2}
F_p2_sys fp2{mod,w2}; // p,w2
F_p2_node t{b,1}; // a,b(means a+bw)
auto x = fp2.pow(t,mod+1>>1);
x0 = to_std(x.a); // assert(x.b==0);
x1 = mod-x.a;
if (x0 > x1) swap(x0,x1);
return true;
}
};

二次剩余的判定及Cipolla算法的更多相关文章

  1. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

  2. 二次剩余定理及Cipolla算法入门到自闭

    二次剩余定义: 在维基百科中,是这样说的:如果q等于一个数的平方模 n,则q为模 n 意义下的二次剩余.例如:x2≡n(mod p).否则,则q为模n意义下的二次非剩余. Cipolla算法:一个解决 ...

  3. Cipolla算法学习小记

    转自:http://blog.csdn.net/doyouseeman/article/details/52033204 简介 Cipolla算法是解决二次剩余强有力的工具,一个脑洞大开的算法. 认真 ...

  4. Cipolla算法学习笔记

    学习了一下1个$\log$的二次剩余.然后来水一篇博客. 当$p$为奇素数的时候,并且$(n, p) \equiv 1 \pmod{p}$,用Cipolla算法求出$x^2 \equiv n \pmo ...

  5. 二次剩余 Cipolla算法

    欧拉准则 \(a\)是\(p\)的二次剩余等价于\(a^{\frac{p-1}{2}}\equiv 1\pmod p\),\(a\)不是\(p\)的二次剩余等价于\(a^{\frac{p-1}{2}} ...

  6. 【模板】【数论】二次剩余Cipolla算法,离散对数BSGS 算法

    Cipolla LL ksm(LL k,LL n) { LL s=1; for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo; return s; } n ...

  7. HDU 2444 The Accomodation of Students (偶图判定,匈牙利算法)

    题意: 有一堆的学生关系,要将他们先分成两个组,同组的人都不互不认识,如果不能分2组,输出No.若能,则继续.在两组中挑两个认识的人(每组各1人)到一个双人房.输出需要多少个双人房? 思路: 先判定是 ...

  8. Java虚拟机判定对象存活算法

    1.引用计数算法 描述:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器值为0的对象就是不可能再被使用的. 特点:实现简单,判定效率高. ...

  9. 梅森素数 判定总结 - Lucas-Lehmer算法 & Miller-rabin算法

    梅森素数 定义: if m是一个正整数 and 2^m-1是一个素数 then m是素数 if m是一个正整数 and m是一个素数 then M(m)=2^m-1被称为第m个梅森数 if p是一个素 ...

随机推荐

  1. Docker深入浅出系列 | 单节点多容器网络通信

    目录 教程目标 准备工作 带着问题开车 同一主机两个容器如何相互通信? 怎么从服务器外访问容器 Docker的三种网络模式是什么 Docker网络通信原理 计算机网络模型回顾 Linux中的网卡 查看 ...

  2. UVA1623 Enter The Dragon (贪心)

    题意: m个坑,n天,起初每个坑都是满的,每天至多有一个坑会下雨,下雨就会满,满了再下就输出no. 在没有雨的时候可以安排龙来喝水,把坑喝空,可行的话输出龙喝水的方案 思路: 边读入边操作,set保存 ...

  3. Ansible:roles初始化系统

    简介 本文介绍ansible的roles,通过roles来实现系统的初始化,其相当于将ansible的playbook拆分.本文通过Jenkins,传参,调用playbook来初始化系统. Githu ...

  4. 【MySQL 线上 BUG 分析】之 多表同字段异常:Column ‘xxx’ in field list is ambiguous

    一.生产出错! 今天早上11点左右,我在工作休息之余,撸了一下猫.突然,工作群响了,老大在里面说:APP出错了! 妈啊,这太吓人了,因为只是说了出错,但是没说错误的信息.所以我赶紧到APP上看看. 这 ...

  5. CNN中的feature map

    个人学习CNN的一些笔记,比较基础,整合了其他博客的内容 feature map的理解在cnn的每个卷积层,数据都是以三维形式存在的.你可以把它看成许多个二维图片叠在一起(像豆腐皮竖直的贴成豆腐块一样 ...

  6. 二叉树的非递归遍历C++实现

    #include<iostream> #include<stdlib.h> #define maxsize 100 using namespace std; typedef s ...

  7. Elasticsearch原理学习--为什么Elasticsearch/Lucene检索可以比MySQL快?

    转载于:http://vlambda.com/wz_wvS2uI5VRn.html 同样都可以对数据构建索引并通过索引查询数据,为什么Lucene或基于Lucene的Elasticsearch会比关系 ...

  8. python图片处理PIL

    一.PIL介绍 PIL中所涉及的基本概念有如下几个:通道(bands).模式(mode).尺寸(size).坐标系统(coordinate system).调色板(palette).信息(info)和 ...

  9. 杭电-------2048不容易系列之(4)考新郎(C语言)

    /* 思路:有n位新郎,但是又m位新郎会找错,那么有n-m位新郎会找对,而找对的n-m位新郎的找发就是在 n位新郎中随机找n-m位有多少种排列组合公式有n!/(m!*(n-m!)),而另外找错的新郎则 ...

  10. jsessionid與cookie關係的理解

    本地測試地址為http://localhost/TEST/login.jsf 當瀏覽器打開cookie時,瀏覽器第一次與服務器建立連接,會創建一個session,並生成一個id即jsessionid, ...