二次剩余

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. spring实战第二章小记-装配bean

    时间:2020/02/06 一.思想 1.创建应用对象之间协作关系的行为通常称为装配,这也是依赖注入(DI)的本质. 对于上面这句话的个人理解:当我们在new一个对象时如果传入了别的对象作为参数(这个 ...

  2. 快乐编程大本营【java语言训练班】第5课: java的数组编程

    快乐编程大本营[java语言训练班]第5课: java的数组编程 第1节. 声明数组变量 第2节. 创建数组对象 第3节. 访问数组元素 第4节. 修改数组元素 第5节. 多维数组 学习地址如下:ht ...

  3. 全国疫情精准定点动态更新(.net core)

    前言 疫情远比我们在年初想的发展迅速,在过年前还计划着可以亲戚聚聚,结果都泡汤了,开始了自家游. 在初三的时候,看到那个丁香医生,觉得不够详细,比如说我想看下周边城市的疫情情况,但是我地理不好,根本不 ...

  4. python函数2(返回值、传递列表...)

    python函数2(返回值.传递列表...) 1.返回值 1.1.返回简单的值 #返回简单值 def get_formatted_name(first_name,last_name): "& ...

  5. 使用小书匠及markdown here编辑博客和微信公众号

    1. 使用小书匠连接Evernote并发布笔记到博客园 1.1 小书匠初探 我平时的信息收集的主要方法是采用Pocket+Evernote. 简单来说: 如果访问到非常有用,而且是必须要立刻记录的内容 ...

  6. Deeplab

    Deeplab系列是谷歌团队的分割网络. DeepLab V1 CNN处理图像分割的两个问题 下采样导致信息丢失 maxpool造成feature map尺寸减小,细节信息丢失. 空间不变性 所谓空间 ...

  7. Disk:磁盘管理之LVM和系统磁盘扩容

    简介 小伙伴们好,好久不见,今天想给大家介绍一下关于磁盘管理的方法和心得:磁盘管理可谓运维工作中的重要内容,主要包括磁盘的合理规划以及扩缩容 常用的磁盘管理方法为LVM(Logical Volume ...

  8. create-react-app 打包后静态文件过大 webpack优化

    在最近的项目里,页面和静态文件并不是很多的情况下,打包后发现产出的静态资源却很大. 1.关掉sourcemap 在config/webpack.config.js文件里,大概30几行的位置添加这样一句 ...

  9. CNN卷积神经网络入门整合(科普向)

    这是一篇关于CNN入门知识的博客,基本手法是抄.删.改.查,就算是自己的一个笔记吧,以后忘了多看看.   1.边界检测示例假如你有一张如下的图像,你想让计算机搞清楚图像上有什么物体,你可以做的事情是检 ...

  10. golang搭建一个简单的web服务器

    package main import ( "io/ioutil" "log" "net/http" ) func main() { htt ...