二次剩余学习笔记
# 二次剩余
当存在数使得成立时,称n是模p意义下的二次剩余(QR)。
特别的,对于,每一个整数都是它的二次剩余;
本文中符号代表二次剩余,代表非二次剩余
下面只考虑为奇素数的情况。
# 若p为奇素数,则恰有个模p的二次剩余,且恰有个模p的非二次剩余
下面的同余式默认省略符号
设,首先证明
显然
这么一来,可知
接下来只需要证明两两不相等即可
假设,且
若,则整除
显然,因此与互质;
又因为,唯一的可能便是,与假设相违背
命题得证
#
请自行证明
# 勒让德符号(legendre symbol)
设为奇素数,则
且有欧拉准则:
式(1)证明略
# Cipolla
算法步骤:
对于,随机找一个使得为非二次剩余,定义(类比虚数)
那么
证明见参考资料
# 模板
#define ll long long
namespace residue{
// p 必须是奇素数
ll square_i = 0, mod = 1;
struct complex{
ll real, imag;
complex operator *(const complex & p){
return {(real * p.real % mod + square_i * p.imag % mod * imag % mod) % mod,
(real * p.imag + imag * p.real) % mod};
}
};
complex qpow(complex a, ll t){
complex res = {1, 0};
while(t){
if(t & 1) res = res * a;
t >>= 1, a = a * a;
}
return res;
}
bool is_residue(ll n, ll p){ // 判断n是否是剩余
ll res = 1, t = (p - 1) / 2;
while(t){
if(t & 1) res = res * n % p;
t >>= 1, n = n * n % p;
}
return res == 1;
}
pair<ll, ll> get_res(ll n, ll p){
n %= p, mod = p;
if(n == 0) return {0, 0};
if(!is_residue(n, p)) return {-1, -1}; // 非二次剩余
ll a;
do{
a = rand() % (p - 1) + 1;
square_i = (a * a % p - n + p) % p;
}while(is_residue(square_i, p));
ll ans1 = qpow({a, 1}, (p + 1) / 2).real, ans2 = p - ans1;
if(ans1 > ans2) swap(ans1, ans2);
return {ans1, ans2};
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 参考资料
- 《数论概论》第4版
- 《哈代数论》第6版
- https://www.cnblogs.com/zwfymqz/p/10605181.html
- https://www.luogu.com.cn/blog/_post/181742
上次更新: 2021/02/24, 03:37:30