二次剩余

\(\text{Problem}:\)【模板】二次剩余

\(\text{Solution}:\)

本文介绍 \(\text{Cipolla}\) 算法,下面默认模数 \(p\) 为奇质数。

定义:

非零数 \(n\) 是模 \(p\) 的二次剩余,当且仅当模 \(p\) 意义下方程 \(x^{2}\equiv n\) 有解。无解情况对应的 \(n\) 称为非二次剩余。

解的数量:

\(p\) 意义下的二次剩余有 \(\dfrac{p-1}{2}\) 个,非二次剩余有 \(\dfrac{p-1}{2}\) 个。

证明:

显然,如果模 \(p\) 意义下 \(x^{2}\equiv n\) 有解,那么当 \(x\in[1,\dfrac{p-1}{2}]\) 时可以取到所有 \(n\)。现在只需证明当 \(x\in[1,\dfrac{p-1}{2}]\) 时,\(x^{2}\text{ mod }p\) 互不相同。

假设存在 \(x,y\in[1,\dfrac{p-1}{2}],x\not=y\) 满足 \(x^{2}\equiv y^{2}\pmod p\),则有 \((x+y)(x-y)\equiv 0\pmod p\)。而 \(x-y\not=0,x+y\not=0\),故假设不成立,原命题得证。


欧拉判别准则:

\(n\) 是模 \(p\) 意义下的二次剩余,当且仅当 \(n^{\frac{p-1}{2}}\equiv1\pmod p\)

\(n\) 是模 \(p\) 意义下的非二次剩余,当且仅当 \(n^{\frac{p-1}{2}}\equiv -1\pmod p\)

证明:

由费马小定理,有 \(n^{p-1}\equiv 1\pmod p\),即 \((n^{\frac{p-1}{2}}-1)(n^{\frac{p-1}{2}}+1)\equiv 0 \pmod p\)。故有:

\[n^{\frac{p-1}{2}}\equiv \pm 1\pmod p \]

\(n\) 是模 \(p\) 意义下的二次剩余,有 \(n^{\frac{p-1}{2}}\equiv (x^{2})^{\frac{p-1}{2}}\equiv x^{p-1}\equiv 1\pmod p\)

\(n^{\frac{p-1}{2}}\equiv 1\pmod p\),设 \(a\)\(p\) 的一个原根,则存在 \(k\in[1,p-1]\),使得 \(n\equiv a^{k}\pmod p\),有:

\[(a^{k})^{\frac{p-1}{2}}\equiv 1\pmod p \]

\(p-1\mid \dfrac{k(p-1)}{2}\),得出 \(k\) 为偶数。令 \(j=\dfrac{k}{2},j\in \Z\),满足 \((a^{j})^2\equiv n\pmod p\),即 \(n\) 是模 \(p\) 意义下的二次剩余。

由以上证明,\(n\) 是模 \(p\) 意义下的二次剩余,与 \(n^{\frac{p-1}{2}}\equiv 1\pmod p\) 等价。原命题得证。


\(\text{Cipolla}\) 算法:

随机一个数 \(a\) 满足 \(a^{2}-n\) 是模 \(p\) 意义下的非二次剩余。期望约 \(2\) 次即可找到满足条件的 \(a\)

定义 \(i^{2}\equiv a^{2}-n\pmod p\),使得所有数可以用 \(A+Bi\) 的形式表达(可以借助复数域理解)。

引理 \(1\)

\[i^{p}\equiv -i\pmod p \]

证明:

\[\begin{aligned} i^{p}&\equiv (i^{2})^{\frac{p-1}{2}}\cdot i\\ &\equiv(a^{2}-n)^{\frac{p-1}{2}}\cdot i\\ &\equiv -i\pmod p \end{aligned} \]

引理 \(2\)

\[(a+b)^p=a^p+b^p\pmod p \]

证明:

\[\begin{aligned} (a+b)^p&=\sum\limits_{i=0}^{p}\binom{p}{i}a^ib^{p-i}\\ &=\sum\limits_{i=0}^{p}\cfrac{a^ib^{p-i}(p-1)!\cdot p}{i!(p-i)!}\\ &=a^{p}+b^{p}\pmod p \end{aligned} \]

现在开始推导 \(n\) 的变换,有:

\[\begin{aligned} n&\equiv a^2-i^2\\ &\equiv (a+i)(a-i)\\ &\equiv (a+i)(a+i^p)\\ &\equiv (a+i)(a^p+i^p)\\ &\equiv (a+i)^{p+1} \end{aligned} \]

由于 \(p+1\) 是偶数,所以存在 \(x\),满足 \(x^2\equiv n\equiv (a+i)^{p+1}\pmod p\)。利用快速幂即可在 \(O(\log p)\) 的时间复杂度内求解。

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,P,I2;
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=1ll*x*x%P) if(p&1) res=1ll*res*x%P; return res; }
struct Node
{
	int x,y;
};
inline Node operator + (Node a,Node b) { return (Node){a.x+b.x,a.y+b.y}; }
inline Node operator - (Node a,Node b) { return (Node){a.x-b.x,a.y-b.y}; }
inline Node operator * (Node a,Node b) { return (Node){(1ll*a.x*b.x%P+1ll*a.y*b.y%P*I2%P)%P,(1ll*a.x*b.y%P+1ll*a.y*b.x%P)%P}; }
inline bool Check(int x)
{
	return ksc(x,(P-1)/2)==1;
}
inline int Rand()
{
	int w=1ll*rand()*rand()%P;
	w+=rand()-rand();
	w=(w%P+P)%P;
	return w;
}
inline Node KSC(Node x,int p)
{
	Node res=(Node){1,0};
	for(;p;p>>=1, x=x*x) if(p&1) res=res*x;
	return res;
}
inline void Solve()
{
	n%=P;
	int a=0;
	if(!n) { puts("0"); return; }
	if(!Check(n)) { puts("Hola!"); return; }
	while(Check((1ll*a*a%P-n+P)%P)) a=Rand();
	I2=(1ll*a*a%P-n+P)%P;
	int X1=KSC((Node){a,1},(P+1)/2).x;
	int X2=P-X1;
	if(X1>X2) swap(X1,X2);
	if(X1==X2) printf("%d\n",X1);
	else printf("%d %d\n",X1,X2);
}
signed main()
{
	srand(time(NULL));
	for(ri int T=read();T;T--)
	{
		n=read(), P=read();
		Solve();
	}
	return 0;
}
posted @ 2021-04-20 20:58  zkdxl  阅读(263)  评论(0编辑  收藏  举报