二次剩余
一个数
对二次剩余求解,也就是对常数
通俗一些,可以认为是求模意义下的开方。这里只讨论
解的数量¶
对于
证明¶
一个显然的性质是
接下来我们只需要证明当
运用反证法,假设存在不同的两个整数
则有
显然
勒让德符号¶
通过勒让德符号可以判断一个数
下表为部分勒让德符号的值
欧拉判别准则¶
若
若
证明¶
由于
其中
因此
设
令
Cipolla 算法¶
找到一个数
建立一个"复数域",并不是实际意义上的复数域,而是根据复数域的概念建立的一个类似的域。 在复数中
在有了
证明¶
- 定理 1:
(a+b)^p\equiv a^p+b^p\pmod p
可以发现只有当
- 定理 2:
i^p\equiv -i\pmod p
- 定理 3:
a^p\equiv a \pmod p
有了这三条定理之后可以开始推导
参考实现
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 46 47 48 49 50 51 52 | #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll n, p;
ll w;
struct num { //建立一个复数域
ll x, y;
};
num mul(num a, num b, ll p) { //复数乘法
num ans = {0, 0};
ans.x = ((a.x * b.x % p + a.y * b.y % p * w % p) % p + p) % p;
ans.y = ((a.x * b.y % p + a.y * b.x % p) % p + p) % p;
return ans;
}
ll binpow_real(ll a, ll b, ll p) { //实部快速幂
ll ans = 1;
while (b) {
if (b & 1) ans = ans * a % p;
a = a * a % p;
b >>= 1;
}
return ans % p;
}
ll binpow_imag(num a, ll b, ll p) { //虚部快速幂
num ans = {1, 0};
while (b) {
if (b & 1) ans = mul(ans, a, p);
a = mul(a, a, p);
b >>= 1;
}
return ans.x % p;
}
ll cipolla(ll n, ll p) {
n %= p;
if (p == 2) return n;
if (binpow_real(n, (p - 1) / 2, p) == p - 1) return -1;
ll a;
while (1) { //生成随机数再检验找到满足非二次剩余的a
a = rand() % p;
w = ((a * a % p - n) % p + p) % p;
if (binpow_real(w, (p - 1) / 2, p) == p - 1) break;
}
num x = {a, 1};
return binpow_imag(x, (p + 1) / 2, p);
}
|
Tonelli-Shanks 算法¶
大致思路如下:
先令
针对
如果
- 因为
a p a^{\frac{p-1}{2}} \equiv 1 \pmod p \sqrt{a^{\frac{p-1}{2}}} \equiv 1 \pmod p - 由 1 可知,
x \equiv \sqrt{a^{\frac{p-1}{2}} \times a} \pmod p - 注意到
s = 1 x \equiv \sqrt{a^{t} \times a} \pmod p x \equiv a^{\frac{t+1}{2}} \pmod p
因此
对于
- 由欧拉判别准则可知
a^{\frac{p-1}{2}} \equiv 1 \pmod p a^{2^{(s-1)} \times t} \equiv 1 \pmod p - 稍作变形得到
\left(a^{-1} \times \left(a^{\frac{t+1}{2}}\right)^{2}\right)^{2^{s-1}} \equiv 1 \pmod p) \left(a^{-1} \times x_{s-1}^{2}\right)^{2^{s-1}} \equiv 1 \pmod p
所以
接下来设
假设我们已经知道
现在的任务变成了计算
对于第一种情况,容易得到:
对于第二种情况,则有:
寻找
接下来寻找一个非二次剩余
- 因为
b b^{\frac{p-1}{2}} \equiv -1 \pmod p b^{t2^{s-1}} \equiv -1 \pmod p - 稍微变个形得到
b^{t \times 2^{s-k} \times 2^{k-1}} \equiv -1 \pmod p (b^{t \times 2^{k-1}})^{2^{s-k}} \equiv -1 \pmod p q \equiv b^{t \times 2^{k-1}} \pmod p
最后得到
不断迭代即可得到答案。该做法的时间复杂度约为
参考实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import random
# example a, p
a = 8479994658316772151941616510097127087554541274812435112009425778595495359700244470400642403747058566807127814165396640215844192327900454116257979487432016769329970767046735091249898678088061634796559556704959846424131820416048436501387617211770124292793308079214153179977624440438616958575058361193975686620046439877308339989295604537867493683872778843921771307305602776398786978353866231661453376056771972069776398999013769588936194859344941268223184197231368887060609212875507518936172060702209557124430477137421847130682601666968691651447236917018634902407704797328509461854842432015009878011354022108661461024768
p = 30531851861994333252675935111487950694414332763909083514133769861350960895076504687261369815735742549428789138300843082086550059082835141454526618160634109969195486322015775943030060449557090064811940139431735209185996454739163555910726493597222646855506445602953689527405362207926990442391705014604777038685880527537489845359101552442292804398472642356609304810680731556542002301547846635101455995732584071355903010856718680732337369128498655255277003643669031694516851390505923416710601212618443109844041514942401969629158975457079026906304328749039997262960301209158175920051890620947063936347307238412281568760161
b = random.randint(1, p)
while (pow(b, (p-1)//2, p) == 1):
b = random.randint(1, p)
t = p - 1
s = 0
while (t % 2 == 0):
s += 1
t = t // 2
x = pow(a, (t + 1) // 2, p)
e = pow(a, t, p)
k = 1
while (k < s):
if (pow(e, 1 << (s - k - 1), p) != 1):
x = x * pow(b, (1 << (k - 1)) * t, p) % p
e = pow(a, p-2, p) * x % p * x % p
k += 1
print(x)
|
习题¶
参考文献¶
https://en.wikipedia.org/wiki/Quadratic_residue
https://en.wikipedia.org/wiki/Euler%27s_criterion
https://blog.csdn.net/doyouseeman/article/details/52033204
build本页面最近更新:,更新历史
edit发现错误?想一起完善? 在 GitHub 上编辑此页!
people本页面贡献者:OI-wiki
copyright本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用