二次剩余

二次剩余

若方程 \(x^k \equiv a \pmod{m}\) 有解,则称 \(a\) 是模 \(m\)\(k\) 次剩余,否则称 \(a\) 是模 \(m\)\(k\) 次非剩余。下面只讨论 \(k=2\) 的情况,即二次剩余(平方剩余)。

先提出几个关键的定理(下面的 \(p\) 均为奇质数):

定理 1:若 \(a\) 是模 \(p\)\(k\) 次剩余,\(b\) 是模 \(p\)\(k\) 次非剩余,则 \(ab\) 是模 \(p\)\(k\) 次非剩余。

证明:若 \(ab\) 是模 \(p\)\(k\) 次剩余,可以设 \(x_1^k \equiv a \pmod{p}, x_2^k \equiv ab \pmod{p}\),于是 \(x_2^k \equiv x_1^k b \pmod{p}\)

  • \(x_1 \equiv 0 \pmod{p}\),则 \(ab \equiv 0 \pmod{p}\),与 \(ab\)\(k\) 次非剩余矛盾。

  • \(x_1 \not\equiv 0 \pmod{p}\),则 \((x_2x_1^{-1})^k \equiv b \pmod{p}\)\(p\) 为奇质数,\(x_1^{-1}\) 一定存在)。这与 \(b\)\(k\) 次非剩余矛盾。

\(\square\)

定理 2:在模 \(p\)简化剩余系中,二次剩余和二次非剩余各占 \(\dfrac{p-1}{2}\)

证明:设 \(p \nmid x\)(简化剩余系),于是 \(x\) 可以写成 \(pq+r\),其中 \(q,r\) 为整数,且 \(|r| \le \dfrac{p-1}{2}\)

于是得出 \(x^2 = (pq+r)^2 \equiv r^2 \pmod{p}\)

发现 \(\forall 1 \le s < t \le \dfrac{p-1}{2}: t^2 - s^2 = (t-s) (t+s)\),其中 \(1 \le t+s,t+s \le p-1\),于是 \((t-s) \not\equiv 0 \pmod{p},(t+s) \not\equiv 0 \pmod{p}\),由于 \(p\) 为奇质数,于是 \((t-s) (t+s) \not\equiv 0 \pmod{p}\)

\(\forall 1 \le s < t \le \dfrac{p-1}{2}: t^2 - s^2 \not\equiv 0 \pmod{m}\)

这说明若 \(x^2 \equiv a \pmod{m}\) 有解,设其中任意两解为 \(s,t\),则有 \(s^2 - t^2 \equiv 0 \pmod{p}\),而上面说明了这只能在 \(s = -t\)\(s = t\) 时成立。

于是 \(1^2, 2^2, \dots, \left(\dfrac{p-1}{2}\right)^2\) 代表了模 \(p\) 的全部二次剩余,其余为模 \(p\) 的二次非剩余。

\(\square\)

定理 3:模 \(p\) 的两个二次非剩余的乘积是模 \(p\) 的二次剩余。

证明:设 \(a,b\) 为模 \(p\) 的两个二次非剩余。根据 定理 1定理 2 可得,\(1^2a, 2^2 a,\dots, \left(\dfrac{p-1}{2}\right)^2 a\) 均为二次非剩余。且 \(ab\) 和它们模 \(p\) 两两不同余,于是 \(ab\) 只能为二次剩余。

\(\square\)

勒让德符号

勒让德符号可以方便我们研究二次剩余:

定义(勒让德符号):

\[\left(\dfrac{a}{p}\right) = \left\{ \begin{aligned} &0 &p \mid a\\ &1 &p \nmid a,且 a 是模 p 的二次剩余\\ &-1 &p \nmid a,且 a 是模 p 的二次非剩余\\ \end{aligned} \right . \]

根据 定理 3 可以得出,\(\left(\dfrac{ab}{p}\right) = \left(\dfrac{a}{p}\right) \left(\dfrac{b}{p}\right)\)

Euler 判别条件

判定二次剩余只需要求出对应的勒让德符号的值,接下来引入 Euler 判别条件,用于求解 \(p\) 为奇质数时的勒让德符号。

利用二次互反律的方法在 Competive Programming 中不优于 Euler 判别条件,故不作介绍。

定理 5(Euler 判别条件):设 \(a \in \mathbb{Z}\)\(p\) 为奇质数,则 \(a^{\frac{p-1}{2}} \equiv \left(\dfrac{a}{p}\right) \pmod{p}\)

证明:若 \(p \mid a\),则 \(\left(\dfrac{a}{p}\right) \equiv a^{\frac{p-1}{2}} \equiv 0 \pmod{p}\)。于是不妨设 \(p \nmid a\)

\(\left(\dfrac{a}{p}\right) = 1\),则 \(\exists x \in \mathbb{Z}: x^2 \equiv a \pmod{p}\),于是 \(a^{\frac{p-1}{2}} \equiv x^{p-1} \equiv 1 \pmod{p}\)\(p\) 为奇质数,由费马小定理可得)。

\(\left(\dfrac{a}{p}\right) = -1\)。则 \(1^2, 2^2, \dots, \left(\dfrac{p-1}{2}\right)^2\) 代表了模 \(p\) 的所有二次剩余,且 \(1^2a, 2^2a, \dots, \left(\dfrac{p-1}{2}\right)^2a\) 代表了模 \(p\) 的所有二次非剩余(由 定理 2 可得),于是它们两两不同余,构成了 \(p\) 的一个简化剩余系。

于是 \(\prod\limits_{i=1}^{\frac{p-1}{2}} i^2 ai^2 \equiv \prod\limits_{r=1}^{n-1} r \equiv -1 \pmod{p}\)。即 \(a^{\frac{p-1}{2}}\left(\prod\limits_{i=1}^{\frac{p-1}{2}} i^2\right)^2 \equiv -1 \pmod{p}\)。注意到左边后面一块带平方,于是里面的累乘可以不管符号,不妨把 \(i^2\) 改写成 \(-i^2\),于是有 \(a^{\frac{p-1}{2}}\left(\prod\limits_{i=1}^{\frac{p-1}{2}} (p-i)i\right)^2 \equiv -1 \pmod{p}\),即 \(a^{\frac{p-1}{2}}(p-1)!^2 \equiv -1 \pmod{p}\),由于 \((p-1)! \equiv -1 \pmod{p}\),于是 \(a^{\frac{p-1}{2}}\equiv -1 \pmod{p}\)

\(\square\)

Cipolla 算法

Cipolla 算法可以求解 \(x^2 \equiv n \pmod{p}\)\(p\) 为奇质数,\(x\) 是模 \(p\) 的二次剩余,且 \(p \nmid n\)),算法流程如下。

  1. 随机寻找一个 \(a\),满足 \(a^2 - n\) 是模 \(p\) 的二次非剩余。
  2. \(i^2 \equiv a^2 - n \pmod{p}\),这里由于 \(a^2 - n\) 是模 \(p\) 的二次非剩余,需要扩域计算(类似复数)。
  3. 求出 \((a+i)^{\frac{p+1}{2}}\) 即为方程的一个解。

通过证明以下引理来证明算法的时间复杂度和正确性:

引理 1:第一步期望 \(2\) 次随机即可找到需要的二次非剩余。

证明:列出关于 \(x\) 的方程 \(x^2 \equiv a^2 - n \pmod{p}\),第一步即找出一个 \(a\),使得这个方程无解。

移项可得 \(a^2 - x^2 \equiv n \pmod{p}\),分解平方差:\((a-x) (a+x)\equiv n \pmod{p}\)

由于 \(p \nmid n\),于是等号能成立当且仅当 \(a-x \not\equiv 0 \pmod{p}\)\(a+x \not\equiv 0 \pmod{p}\)

在模 \(p\) 意义下,能满足 \(bc \equiv n \pmod{p}\)\((b,c)\) 恰有 \(p-1\) 对,即 \(b = 1,2,\dots,p-1,c = b^{-1}\)。将 \(a-x\) 视为 \(b\)\(a+x\) 视为 \(c\),则 \((a-x,a+x)\)\(p-1\) 种。

不难发现,一个使方程有正整数解的 \(a\) 对应了两种不同的解 \(x\)\(x\) 是一个解,则 \(-x\) 也是一个解),又因为 \(n\) 是二次剩余,于是使得方程有解 \(x=0\)\(a\) 恰有两个,而按照上面的讨论方式,\(a-x = a+x\) 对应了两种情况。于是使得方程有解的 \(a\) 共有 \(\dfrac{p+1}{2}\) 个,剩下的 \(\dfrac{p-1}{2}\)\(a\) 都会使方程无解。

\(p\) 足够大时,可以认为使得方程有解和无解的概率各占 \(\dfrac{1}{2}\)

\(\square\)

引理 2\((a+i)^{p+1} \equiv n \pmod{p}\)

证明:拆开:\((a+i)^{p+1} = (a+i)^p (a+i)\)

对前面一项用二项式定理展开,注意到 \(\forall 1 \le i \le p-1:\dbinom{p}{i} \equiv 0 \pmod{p}\)(由 \(p\) 是奇质数容易得到)。于是 \((a+i)^p \equiv a^p + i^p \pmod{p}\)

由于 \(a^2 - n\) 是模 \(p\) 的二次非剩余,于是根据 定理 5(Euler 判别条件)可得 \((a^2 - n)^{\frac{p-1}{2}} \equiv -1 \pmod{p}\),即 \(i^{p-1} \equiv -1 \pmod{p}\),由费马小定理得 \(a^p \equiv a \pmod{p}\)

于是 \((a^p+i^p) (a+i) \equiv (a-i) (a+i) \equiv a^2 - i^2 \equiv a^2 - a^2 + n \equiv n \pmod{p}\)

\(\square\)

引理 3\((a+i)^{\frac{p+1}{2}}\) 在模 \(p\) 意义下的结果不含 \(i\)

证明:若存在一个 \(b+ci\),满足 \(c \not\equiv 0 \pmod p,(b+ci)^2 \equiv n \pmod{p}\),则 \(b^2 + 2bci + c^2(a^2 - n) \equiv n \pmod{p}\)

把“实部”和“虚部”分别放到两边:\(b^2 + c^2(a^2 - n) -n \equiv - 2bci \pmod{p}\),类似复数,等式成立当且仅当左右两边均为 \(0\)。考虑右边的“虚部”:由于 \(c \not\equiv 0 \pmod p\),那么一定有 \(b \equiv 0 \pmod p\),那么 \((ci)^2 = c^2(a^2 - n) \equiv n \pmod{p}\),于是 \(a^2 - n \equiv n(c^{-1})^2 \pmod{p}\)。由于 \(n\) 是二次剩余,\((c^{-1})^2\) 显然是二次剩余,于是 \(a^2 - n\) 是二次剩余。

这和算法第一步要求的 \(a^2 - n\) 是二次非剩余矛盾。

\(\square\)

于是 Cipolla 算法可以在期望 \(O(\log p)\) 的的时间内求解方程 \(x^2 \equiv n \pmod{p}\)

实现

题目

#include <bits/stdc++.h>

using namespace std;

struct Complex {
    Complex() {r=i=0;};
    Complex(int v) {r=v;i=0;}
    Complex(int r,int i):r(r),i(i) {}
    int r,i;
};

int sq,mod;
mt19937 rng(random_device{}());

Complex operator+(const Complex &a,const Complex &b) {return Complex((a.r+b.r)%mod,(a.i+b.i)%mod);}
Complex operator*(const Complex &a,const Complex &b) {
    return Complex((1ll*a.r*b.r%mod+1ll*a.i*b.i%mod*sq%mod)%mod,(1ll*a.r*b.i%mod+1ll*a.i*b.r%mod)%mod);
}

Complex qpow(Complex a,int b) {
    Complex res=1;
    for(;b;b>>=1,a=a*a) {
        if(b&1) res=res*a;
    }
    return res;
}

int qpow(int a,int b,int mod) {
    int res=1;
    for(;b;b>>=1,a=1ll*a*a%mod) if(b&1) res=1ll*res*a%mod;
    return res;
}

bool check(int n,int p) {return n?qpow(n,(p-1)/2,p)==1:true;}

int Cipolla(int n,int p) {
    mod=p; n%=mod;
    if(n==0) return 0;
    uniform_int_distribution<int> gen(0,p-1);
    int a=gen(rng);
    while(check((1ll*a*a%mod+mod-n)%mod,p)) a=gen(rng);
    sq=(1ll*a*a%mod+mod-n)%mod;
    return qpow(Complex(a,1),(p+1)/2).r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);

    int T=0; cin>>T;
    while(T--) {
        int n,p; cin>>n>>p;
        if(!check(n,p)) cout<<"Hola!"<<"\n";
        else {
            int res=Cipolla(n,p);
            if(res>p-res) res=p-res;
            cout<<res;
            if(res) cout<<" "<<p-res;
            cout<<"\n";
        }
    }

    return 0;
}
posted @ 2023-12-13 22:58  xzm111  阅读(109)  评论(0编辑  收藏  举报