浅谈二次剩余

本文只讨论p为奇质数的情况

下面大量内容借用神仙yyc大佬的blogs

才不是因为我懒

概(che)论(dan)

c , p c, p c,p求解

x 2 ≡ c ( m o d p ) x^2 \equiv c \pmod p x2c(modp)

前置芝士

欧拉判别法

首先要知道这个数有没有二次剩余,即 x 2 ≡ c ( m o d p ) x^2 \equiv c \pmod p x2c(modp)是否有解
先给出结论:浅谈二次剩余_第1张图片

证明: 把 c p − 1 2 平 方 一 下 变 成 c ( p − 1 2 ) 2 = c p − 1 = 1 ( 根 据 费 马 小 定 理 , 所 以 开 根 后 为 ± 1 把c^{\frac{p-1}{2}}平方一下变成c^{{(\frac{p-1}{2})}^2} = c^{p-1}=1(根据费马小定理,所以开根后为±1 c2p1c(2p1)2=cp1=1,±1
当 c p − 1 2 = − 1 时 可 以 用 反 证 法 把 x 2 = c 代 入 得 到 x p − 1 ≡ − 1 ( m o d   p ) 显 然 和 费 马 小 定 理 矛 盾 当c^{\frac{p-1}{2}}=-1时可以用反证法把x^2=c代入得到x^{p-1}\equiv-1(mod \ p) 显然和费马小定理矛盾 c2p1=1x2=cxp11(mod p)
或者可以直接简单理解一下如果 c p − 1 2 = − 1 c^{\frac{p-1}{2}}=-1 c2p1=1说明是在原根环的一个偶数点的位置上,那么必定存在一个位置平方是这个偶数位置

二次剩余个数

p − 1 2 个 \large \frac{p-1}{2}个 2p1
引 理 : c 2 ≡ ( p − c ) 2 ( m o d p ) , 就 相 当 于 c 2 和 ( − c ) 2 引理:c^2 \equiv (p-c)^2 \pmod p,就相当于c^2和(-c)^2 c2(pc)2(modp),c2(c)2

我 们 定 义 一 个 奇 怪 的 东 西 : ( a p ) 表 示 上 面 那 个 东 西     又 叫 勒 让 德 符 号 ( l e g e n d r e s y m b o l ) 我们定义一个奇怪的东西:\large ( \frac{a}{p}) 表示上面那个东西 \ \ \ 又叫 勒让德符号 (legendre symbol) 西:(pa)西   (legendresymbol)
浅谈二次剩余_第2张图片
有下列性质:
( a b p ) = ( a p ) ( b p ) \large ( \frac{ab}{p})=\large ( \frac{a}{p})\large ( \frac{b}{p}) (pab)=(pa)(pb)

( q p ) ( p q ) = ( − 1 ) p − 1 2 ∗ q − 1 2 \large ( \frac{q}{p})\large ( \frac{p}{q})=(-1)^{\frac{p-1}{2} * \frac{q-1}{2}} (pq)(qp)=(1)2p12q1

其实还是挺容易理解的

算法流程

假 设 我 们 要 求 n 在 模 p 意 义 下 的 二 次 剩 余 , 即 x 2 ≡ n ( m o d p ) , 求 x 假设我们要求n在模p意义下的二次剩余,即x^2 \equiv n \pmod p,求x npx2n(modp),x
先 随 机 一 个 值 a 使 得 ( a 2 − n ) p − 1 2 = − 1 , 也 就 是 说 a 2 − n 不 是 p 的 二 次 剩 余 。 先随机一个值a使得 (a^2-n)^{\frac{p-1}{2}}=-1,也就是说a^2-n不是p的二次剩余。 a使(a2n)2p1=1a2np
因为上面说了有 p − 1 2 \frac{p-1}{2} 2p1个,所以期望 2 2 2次就能随机到
然 后 我 们 强 行 将 其 开 根 , 这 样 会 得 到 一 个 类 似 虚 数 的 东 西 , 准 确 来 说 时 设 w 2 = ( a 2 − n ) , 学 过 F F T 的 应 该 都 能 理 解 然后我们强行将其开根,这样会得到一个类似虚数的东西,准确来说时设w^2=(a^2-n),学过FFT的应该都能理解 西,w2=(a2n),FFT
可以证明扩系后仍然是环。
引 理 : ( a + b ) p = a p + b p 引理:(a+b)^p = a^p + b^p :(a+b)p=ap+bp
证明直接二项式展开一下再加上Lucas就好了,详细过程可以看yyc的blog
浅谈二次剩余_第3张图片
在这里插入图片描述

所以这么随便搞搞就好了

#include
#define ll long long
using namespace std;
struct cp {
	ll x, y;
};
ll mod, w;
cp mul(cp x, cp y) {return cp{(x.x * y.x % mod + x.y * y.y % mod * w % mod) % mod, (x.x * y.y % mod + x.y * y.x % mod) % mod};}//新运算
cp qpow(cp x, int y) {
	cp ret = {1, 0};
	for(; y; y >>= 1, x = mul(x, x)) if(y & 1) ret = mul(ret, x);
	return ret;
}
void Cipolla(int n, int p) {
	mod = p;
	if(!n) {
		printf("0\n");
		return;
	}
	if(p == 2) {
		printf("1\n");
		return;
	}//0, 2特判
	if(qpow(cp{n, 0}, (mod - 1) >> 1).x == mod - 1) {//如果欧拉判别失败
		printf("Hola!\n");
		return;
	}  
	ll a = rand() % mod;
	while(!a || qpow(cp{w = (a * a - n + mod) % mod, 0}, (mod - 1) >> 1).x == 1) a = rand() % mod;//随机一个a,求得解
	int x0 = qpow(cp{a, 1}, (mod + 1) >> 1).x, x1 = mod - x0;//求出另外
	if(x0 > x1) swap(x0, x1);
	if(x0 != x1) printf("%lld %lld\n", x0, x1);
	else printf("%lld\n", x0);
}
int Q;
int main() {
	srand(time(NULL));
	scanf("%d", &Q);
	while(Q --) {
		ll n, p;
		scanf("%lld%lld", &n, &p);
		Cipolla(n, p);
	}
	return 0;
}

to be continue……

你可能感兴趣的:(数论,二次剩余)