二次剩余

这里就简单记一下二次剩余的一些东西,部分内容没有证明(有些我也不太会)。

定义 1 1 1:设素数 p > 2 , d ∈ Z , p ∤ d p>2,d∈\mathbb Z,p \nmid d p>2,dZ,pd,若 x 2 ≡ d ( m o d p ) x^2\equiv d \pmod p x2d(modp) 有解,称 d d d 是模 p p p 的二次剩余,否则称 d d d 是模 p p p 的二次非剩余。

定理 1 1 1:在模 p p p 的一个既约剩余系中,恰有 p − 1 2 \frac{p-1}{2} 2p1 个模 p p p 的二次剩余, p − 1 2 \frac{p-1}{2} 2p1 个模 p p p 的二次非剩余。若 d d d 是模 p p p 的二次剩余,则 x 2 ≡ d ( m o d p ) x^2\equiv d \pmod p x2d(modp) 的解数为 2 2 2

定理 2 2 2Euler 判别法):设素数 p > 2 p>2 p>2 p ∤ d p\nmid d pd,那么:

  • d d d 是模 p p p二次剩余的充分必要条件是:

d p − 1 2 ≡ 1 ( m o d p ) d^{\frac{p-1}{2}}\equiv1\pmod p d2p11(modp)

  • d d d 是模 p p p非二次剩余的充分必要条件是:

d p − 1 2 ≡ − 1 ( m o d p ) d^{\frac{p-1}2}\equiv-1\pmod p d2p11(modp)

Cipolla 算法

求解关于 x x x 的同余方程:

x 2 ≡ n ( m o d p ) x^2\equiv n\pmod p x2n(modp)

p = 2 p=2 p=2 是很好解,接下来只考虑 p > 2 p>2 p>2 的奇素数的情况。

算法流程是这样的:

  1. 找到 a a a 使得 a 2 − n a^2-n a2n 是模 p p p 意义下的二次非剩余。根据定理 1 1 1,找到满足条件的 a a a 的期望步数是 2 2 2
  2. ω = a 2 − n \omega=\sqrt{a^2-n} ω=a2n ,解出 x 0 = ( a + ω ) p + 1 2 x_0=(a+\omega)^{\frac{p+1}2} x0=(a+ω)2p+1,那么解有两个: x 0 x_0 x0 − x 0 -x_0 x0

简单说一下这样做的正确性吧。

定理 3 3 3 ω p ≡ − ω ( m o d p ) \omega^p\equiv-\omega\pmod p ωpω(modp)

ω p ≡ ω ω p − 1 ≡ ω ( ω 2 ) p − 1 2 ≡ ω ( a 2 − n ) p − 1 2 ≡ − ω ( m o d p ) \omega^p\equiv \omega\omega^{p-1}\equiv\omega(\omega^2)^{\frac {p-1}2}\equiv\omega(a^2-n)^{\frac {p-1}2}\equiv-\omega\pmod p ωpωωp1ω(ω2)2p1ω(a2n)2p1ω(modp)

定理 4 4 4 ( a + b ) p ≡ a p + b p ( m o d p ) (a+b)^p\equiv a^p+b^p\pmod p (a+b)pap+bp(modp)

用二项式定理展开,发现对于组合数 ( p i ) \binom p i (ip),只有当 i = 0 i=0 i=0 i = p i=p i=p 时不含 p p p 这个因子,其他的都被模掉了。

那么对于解 x 0 = ( a + ω ) p + 1 2 x_0=(a+\omega)^{\frac{p+1}2} x0=(a+ω)2p+1,我们可以验证一下:

x 0   2 = ( a + ω ) p + 1 = ( a + ω ) p ( a + ω ) = ( a p + ω p ) ( a + ω ) \begin{aligned} x_0^{\,2}&=(a+\omega)^{p+1}\\ &=(a+\omega)^p(a+\omega)\\ &=(a^p+\omega^p)(a+\omega)\\ \end{aligned} x02=(a+ω)p+1=(a+ω)p(a+ω)=(ap+ωp)(a+ω)

然后由于费马小定律, a p = a ( m o d p ) a^{p}=a\pmod p ap=a(modp),又根据定理 3 3 3,所以:

x 0   2 = ( a − ω ) ( a + ω ) = a 2 − ω 2 = a 2 − ( a 2 − n ) = n \begin{aligned} x_0^{\,2}&=(a-\omega)(a+\omega)\\ &=a^2-\omega^2\\ &=a^2-(a^2-n)\\ &=n \end{aligned} x02=(aω)(a+ω)=a2ω2=a2(a2n)=n

所以这是对的。

由于 a 2 − n a^2-n a2n二次非剩余,需要一个类似于记复数的方式记它。


附上洛谷二次剩余模板的代码:

#include<bits/stdc++.h>
using namespace std;
namespace IO{
	const int Rlen=1<<22|1;
	char buf[Rlen],*p1,*p2;
	inline char gc(){
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	template<typename T>
	inline T Read(){
		char c=gc();T x=0,f=1;
		while(!isdigit(c))  f^=(c=='-'),c=gc();
		while( isdigit(c))  x=(x+(x<<2)<<1)+(c^48),c=gc();
		return f?x:-x;
	}
	inline int in()  {return Read<int>();}
}
using IO::in;
int n,P,I,val;
int add(int x,int y)  {return x+y>=P?x+y-P:x+y;}
int dec(int x,int y)  {return x-y< 0?x-y+P:x-y;}
int mul(int x,int y)  {return 1ll*x*y>=P?1ll*x*y%P:x*y;}
int power(int a,int b){
	int ans=1;
	for(;b;b>>=1,a=mul(a,a))  if(b&1)  ans=mul(ans,a);
	return ans;
}
struct num{
	int x,y;
	num(int x=0,int y=0):x(x),y(y){}
	friend num operator*(const num &a,const num &b){
		return num(add(mul(a.x,b.x),mul(val,mul(a.y,b.y))),add(mul(a.x,b.y),mul(a.y,b.x)));
	}
	friend num operator^(num a,int b){
		num ans(1,0);
		for(;b;b>>=1,a=a*a)  if(b&1)  ans=ans*a;
		return ans;
	}
};
int main(){
	int T=in();
	while(T--){
		n=in(),P=in(),n%=P;
		if(!n)  {puts("0");continue;}
		if(P==2)  {printf("%d\n",n);continue;}
		if(power(n,(P-1)>>1)!=1)  {puts("Hola!");continue;}
		while(1){
			I=rand()%P,val=dec(mul(I,I),n);
			if(power(val,(P-1)>>1)==P-1)  break;
		}
		int x=(num(I,1)^((P+1)>>1)).x;
		x=(P-x<x?P-x:x),printf("%d %d\n",x,P-x);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值