二次剩余(模意义开方)

二次剩余,就是求解方程
x 2 ≡ n ( m o d    p ) x^2\equiv n (\mod p) x2n(modp)
此时 p p p为一个奇素数,就是常规的二次剩余问题

根的数量

我们假设一个方程有多个根那么可以列出 x 0 2 ≡ x 1 2 ( m o d    p ) x_0^2\equiv x_1^2(\mod p) x02x12(modp)

移项之后可得 ( x 1 − x 0 ) ( x 1 + x 0 ) ≡ 0 ( m o d    p ) (x_1-x_0)(x_1+x_0)\equiv0(\mod p) (x1x0)(x1+x0)0(modp)

因为 x 0 x_0 x0, x 1 x_1 x1为两不同的根所以 x 1 − x 0 x_1-x_0 x1x0 p p p不会为 0 0 0

所以 x 1 + x 0 ≡ 0 ( m o d    p ) x_1+x_0\equiv0(\mod p) x1+x00(modp),即 x 0 x_0 x0, x 1 x_1 x1为相反数

因为 p p p为奇素数,所以两根肯定不相同,所以方程必然有两不同根

欧拉准则

那么我们现在解决判断 n n n是否在模 p p p的意义下为二次剩余的问题

先放结论 n p − 1 2 ≡ 1 ( m o d    p ) n^{\frac{p-1}2}\equiv 1(\mod p) n2p11(modp) n n n为模 p p p意义下的二次剩余的充要条件

先证明必要性,由于 n n n为二次剩余由 x p − 1 ≡ 1 ( m o d    p ) x^{p-1}\equiv 1(\mod p) xp11(modp)可知 ( x 2 ) p − 1 2 = n p − 1 2 ≡ 1 ( m o d    p ) (x^2)^{\frac{p-1}2}=n^{\frac{p-1}2}\equiv 1(\mod p) (x2)2p1=n2p11(modp)

再证明充分性, n = g k n=g^k n=gk,其中 g g g为原根,那么 g k p − 1 2 ≡ 1 ( m o d    p ) g^{k\frac{p-1}{2}}\equiv 1(\mod p) gk2p11(modp),由于原根一定不为二次剩余,所以 p − 1 ∣ k p − 1 2 p-1|k\frac{p-1}2 p1∣k2p1所以 k k k必然为偶数,那么 g k 2 g^{\frac k2} g2k即为 n n n的二次剩余。

那么我们便证明了 n p − 1 2 ≡ 1 ( m o d    p ) n^{\frac{p-1}2}\equiv 1(\mod p) n2p11(modp) n n n为模 p p p意义下的二次剩余是等价的

因为 n p − 1 ≡ 1 ( m o d    p ) n^{p-1}\equiv 1(\mod p) np11(modp)所以 n p − 1 2 n^{\frac{p-1}2} n2p1 1 1 1的二次剩余为 1 1 1 − 1 -1 1,所以若 n n n是二次剩余, n p − 1 2 n^{\frac{p-1}2} n2p1的值为 − 1 -1 1

Cipolla

我们现在考虑解方程 x 2 ≡ n x^2\equiv n x2n

首先找到一个 a a a满足 a 2 − n a^2-n a2n是非二次剩余,期望是 2 2 2次即可找到

接下来定义 i 2 ≡ a 2 − n i^2\equiv a^2-n i2a2n,这里的 i i i的定义类似于单位虚数的定义。

然后可以把所有数表示为 A + B i A+Bi A+Bi的形式。

那么我们可以有两个结论

引理1 i p ≡ − i i^p\equiv-i ipi

证明: i p ≡ i ( i 2 ) p − 1 2 ≡ i ( a 2 − n ) p − 1 2 ≡ − i i^p\equiv i(i^2)^{\frac{p-1}2}\equiv i(a^2-n)^{\frac{p-1}2}\equiv-i ipi(i2)2p1i(a2n)2p1i

引理2 ( A + B ) p ≡ A p + B p (A+B)^p\equiv A^p+B^p (A+B)pAp+Bp

证明:由二项式定理,由于 p p p为质数,除了 C p 0 C_p^0 Cp0, C p p C_p^p Cpp外的组合数分子上的阶乘没法消掉,模 p p p 0 0 0,只剩 C p 0 A p + C p p B p C_p^0A^p+C_p^pB^p Cp0Ap+CppBp

最后我们就可以得出结论 ( a + i ) p + 1 ≡ n (a+i)^{p+1}\equiv n (a+i)p+1n

证明:
( a + i ) p + 1 ≡ ( a p + b p ) ( a + i ) ≡ ( a − i ) ( a + i ) ≡ a 2 − i 2 ≡ n (a+i)^{p+1}\equiv(a^p+b^p)(a+i)\equiv(a-i)(a+i)\equiv a^2-i^2\equiv n (a+i)p+1(ap+bp)(a+i)(ai)(a+i)a2i2n
那么 ± ( a + 1 ) p + 1 2 \pm(a+1)^{\frac{p+1}2} ±(a+1)2p+1就是方程的解

code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
struct Com{LL r,i;};
LL w;
Com mul(Com a,Com b,LL P){
	Com c;
	c.r=(a.r*b.r%P+a.i*b.i%P*w%P)%P;
	c.i=(a.r*b.i%P+a.i*b.r%P)%P;
	return c;
}
LL fpowr(LL a,LL b,LL P){LL ret=1;
	for(;b;b>>=1,a=a*a%P)
	if(b&1)ret=ret*a%P;
	return ret;
}
Com fpowc(Com a,LL b,LL P){Com ret={1,0};
	for(;b;b>>=1,a=mul(a,a,P))
	if(b&1)ret=mul(ret,a,P);
	return ret;
}
LL Euler(LL n,LL P){
	return fpowr(n,P-1>>1,P);
}
LL solve(LL n,LL P){
	n%=P;
	LL a;do a=rand()%P;
	while(Euler(w=(a*a%P-n+P)%P,P)!=P-1);
	return fpowc({a,1},P+1>>1,P).r;
}
int main(){
	srand(time(NULL));
	int T;scanf("%d",&T);
	while(T--){
		LL n,P,a,b;
		scanf("%lld%lld",&n,&P);
		if(!n){puts("0");continue;}
		if(Euler(n,P)==P-1){puts("Hola!");continue;}
		else{
			a=solve(n,P),b=P-a;
			if(a>b)swap(a,b);
			printf("%lld %lld\n",a,b);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值