Live2D

二次剩余小记

\(\text{yyb}\) 的博客看到的,发现似乎并没有想象中的那么难,就学了一下,过了板题,这里记录一下,暂时还是只会二次剩余, \(n\) 次剩余暂时先放一下。

模数为奇素数

下文的 \(p\) 即是模数。

我们称 \(n\) 为模 \(p\) 意义下的二次剩余当且仅当存在 \(x\) 使得 \(x^2\equiv n\pmod p,x\in \mathbb{N}\) 。下文的 \(\mathbb{N}\) 其实是自然数集。

  • 引理1

\((A+B)^p\equiv A^p+B^p\pmod{p}\)

  • 证明

显然只需要说明 \(\dbinom{p}{i}\equiv0\pmod p,s.t.\ \ 1\le i\le p-1\),然后我们发现如果 \(p\) 是个奇素数的话,那么分子里面的 \(p\) 就没有办法消去,于是就得证了。

  • 引理2

\(n^{\frac{p-1}{2}}\equiv 1\pmod p\)

\(n\) 是模 \(p\) 意义下的二次剩余的必要条件。

  • 证明

必要性 :设 \(x^2\equiv n\pmod p\),那么有 \(x^{p-1}\equiv 1\pmod p\) ,证毕。

充分性 :显然。


接下来,我们考虑随机出一个 \(a\) 使得 \(a^2-n\) 不是一个二次剩余,这样的期望尝试次数大概为 \(2\),再设 \(i^2=a^2-n\) ,这里的 \(i\) 显然就不属于 \(\mathbb{N}\) ,我们把它视作虚数之类的东西就好了。然后我们发现就有个性质:

  • 性质

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

证明 :首先我们知道 \((i^2)^{\frac{p-1}{2}}\equiv (a^2-n)^{\frac{p-1}{2}}\not\equiv 1\pmod p\) (因为 \(a^2-n\) 不是一个二次剩余),然后又有 \((i^2)^{p-1}\equiv 1\pmod p\),所以 \(i^{p-1}\equiv -1\pmod p\)


我们可(bu)以(neng)发现:

\[(a+i)^{p+1}\equiv (a+i)^p(a+i)\equiv(a^p+i^p)(a+i)\equiv (a-i)(a+i) \]

\[\equiv a^2-i^2\equiv n\pmod p \]

就是说 \((a+i)^{p+1}\equiv n\pmod p\),所以说 \(\sqrt n\equiv (a+i)^{\frac{p+1}{2}}\pmod p\)

可能有人有疑问,\((a+i)^{\frac{p+1}{2}}\) 有没有可能不是一个整数,显然如果你保证有解的话它显然就是一个整数。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define int long long

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}

int p,sqri;

int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = 1ll * a * a % p) if (b & 1) res = 1ll * res * a % p;
	return res;
}
int mul (int a,int b){return 1ll * a * b % p;}
int dec (int a,int b){return a >= b ? a - b : a + p - b;}
int add (int a,int b){return a + b >= p ? a + b - p : a + b;}

struct node{
	int real,imag;
	node (int _real,int _imag) : real (_real) , imag (_imag) {}
	node operator * (node b){return node (add (1ll * real * b.real % p,1ll * imag * b.imag % p * sqri % p),add (1ll * real * b.imag % p,1ll * b.real * imag % p));}
	node operator + (node b){return node (add (real,b.real),add (imag,b.imag));}
	node operator ^ (int b){node a = *this,res = node (1,0);for (;b;b >>= 1,a = a * a) if (b & 1) res = res * a;return res;}
};

bool check_if_qs (int n){//判断是否是一个二次剩余 
	return qkpow (n,(p - 1) >> 1) == 1;
}

bool tryit (int n){
	if (n == 0){
		puts ("0");
		return 1;
	}
	int a = rand ();sqri = dec (mul (a,a),n);
	if (!a || !check_if_qs (sqri)){
		int x0 = (node (a,1) ^ (p + 1 >> 1)).real;
		int x1 = p - x0;if (x0 > x1) swap (x0,x1);
		write (x0),putchar (' '),write (x1),putchar ('\n');
		return 1;
	}
	else return 0;
} 

signed main(){
	int T;read (T);
	while (T --> 0){
		int n;read (n,p);
		if (!check_if_qs (n) && n) puts ("Hola!");
		else while (1) if (tryit (n)) break;
	}
	return 0;
}
posted @ 2020-08-22 08:49  Dark_Romance  阅读(169)  评论(0编辑  收藏  举报