Cornacchia 算法 & P2063 二平方和定理

· · 题解

闲话:在学校不但睡不好而且甚至睡不着,睡眠时间还被新来的校长砍了,而且我没得打 WA2,我甚至还没打完 coda 篇任意一条线路,周日没有休息,恐怕要初赛后才能打。

闲话:很难说这是一个特别的算法,还是一个欧几里得辗转相除的 trick,不过我似乎没有看到一个合适的中文介绍。不论如何,它很方便地解决了我在模拟赛中遇到的问题。

一道模拟赛题

假设我们要解决这样一个问题。

给定一个正整数 2\le n\le 10^{18},构造一组解 (a,b) 满足 a,b 均为非负整数且 a^2+b^2=n,或报告无解。

本题有一些和 Cornacchia 算法完全无关的做法,复杂度从四次根号到几个 \log 都有,但是相比之下 Cornacchia 算法可能更为通用(以及优美)。
对于这个问题,如果使用该算法,主要瓶颈在质因数分解以及二次剩余上。

首先是一些简单的推导。

::::info[“高斯整数”?]{open} 以防有人像我一样不知道什么是高斯整数。

高斯整数是形如 a + bi 的复数,更准确地说,这篇文章中涉及的复数都是高斯整数。 ::::

大家知道,复数相乘时模长相乘。将问题转化一下,考虑去构造一个复数序列 w_{1\cdots k} 使得 |\prod_{i=1}^k w_i|^2=n,当然每个复数的实部和虚部都是非负整数。然后就只需要输出 \prod_{i=1}^k w_i 的实部和虚部就可以了,记得取绝对值。

当然,上面的讨论看起来一点信息量都没有。所以先质因数分解,设 n=\prod_{i=1}^{cnt} p_i^{c_i},对于每个 p_i 分别构造。

  1. 令 $v=1+\mathrm{i}$ 易得 $|v|^2=2$,那么往 $w$ 序列里插入 $c_i$ 个 $1+\mathrm{i}$,即可让 $|\prod w|^2$ 的值乘上 $2^{c_i}$。
  2. - 对于 $c_i\equiv 0 \pmod 2$,往 $w$ 序列里插入 $c_i/2$ 个 $p_i$(注意是高斯整数 $p_i$,更精确地说是 $p_i+0\mathrm{i}$)即可,每个 $p_i$ 对 $|\prod w|^2$ 的贡献显然是 $p_i^2$; - 否则报告无解。 ::::info[为什么无解?] 学过小学奥数的朋友都知道,完全平方数模 $4$ 余 $0$ 或 $1$。 没学过也不用担心,学过抽象代数的朋友都知道,整数中模 $4$ 余 $3$ 的素数 $p$ 在高斯域中是惯性的,$(p)$ 仍然是素理想。 如果都没学过,打表找规律也不失为一个好办法。 你问我初等方法?因为 $p$ 是奇数,若 $p$ 是完全平方数,则 $n=\sqrt p$ 是奇数。设 $n=2k+1(k\in \mathbb N)$,有 $n^2=4k^2+4k+1\equiv 1 \pmod 4$。 ::::
  3. 我断言,我们可以使用 Cornacchia 算法在 $\mathcal O(\log^2 V)$ 时间内构造一组 $(a_i,b_i)$ 满足 $a_i^2+b_i^2=p_i$,然后往 $w$ 里面插入 $c_i$ 个 $a_i+\mathrm{i}b_i$ 即可。根据费马平方和定理,存在满足条件的解 $(a_i,b_i)$。

当然了,实现的时候肯定要用快速幂把相等的复数先积起来,然后把所有东西乘起来。

它的正确性由过程给出。复杂度瓶颈,如前所述,在于写出高效的质因数分解和二次剩余。

P2063 二平方和定理

给定一个正整数 2\le n\le 10^{18},求出所有非负整数数对 (a,b) 满足 a^2+b^2=n

相比于上面那个题,这次我们需要构造所有的解。

可以发现,刚刚关于高斯整数的模型似乎仍然是适用的。
由唯一分解定理可以得到,最终仍旧得先质因数分解到每个质因子,再全部乘起来。
我们试着进一步分析看看,对于每个质数有多少种对应到高斯整数的方法,来试图遍历到所有解。

  1. 仍旧仅有 $1+\mathrm{i}$ 一种可能,在实部和虚部分别枚举 $0,1,2$ 即可得到。
  2. 与刚刚的分析相同,必须得把 $p_i$ 两两配对来产生若干个 $p_i^2$ 的贡献。用同样的手法可以证明,只有 $p_i+0\mathrm i$ 和 $0+p_i\mathrm i$ 两种可能的情况。
  3. 类似的只有两组本质相同的解 $(a_i,b_i)$ 和 $(b_i,a_i)$(容易注意到 $a_i \ne b_i$)。 ::::info[引理,等一会还要用到]{open} 若 $(x,y)$ 是方程 $x^2 + d\cdot y^2 = p$ 的一组非负整数解,且 $y \not \equiv 0 \pmod p$,则 $\pm\sqrt{-d} \equiv x/y \pmod p$。 为了方便和我一样不会数论的朋友,写一下推导。 $$ \begin{aligned} x^2 + d\cdot y^2&\equiv 0 &\pmod p\\ x^2&\equiv -d\cdot y^2 &\pmod p\\ \frac{x^2}{y^2}&\equiv -d &\pmod p\\ \frac{x}{y}&\equiv \pm\sqrt{-d} &\pmod p\\ \end{aligned} $$ :::: ::::info[证明] 假设存在两组不同的非负整数解 $$(a, b)$$ 和 $$(c, d)$$,满足 $$a^2 + b^2 = p$$ 和 $$c^2 + d^2 = p$$,且 $$\{a, b\} \neq \{c, d\}$$。由于 $$p$$ 是质数,显然 $$a, b, c, d$$ 均为正整数。 考虑模 $$p$$ 下的运算。由 $$a^2 + b^2 = p$$, $$c^2 + d^2 = p$$,结合刚刚的讨论,$$a/b$$ 和 $$c/d$$ 都是模 $$p$$ 下 $$-1$$ 的平方根。由于 $$p \equiv 1 \pmod{4}$$,$$-1$$ 的二次剩余恰好有两个互为相反数的解,$$a/b \equiv \pm c/d \pmod{p}$$。 设 $$a/b \equiv c/d \pmod{p}$$,则 $$a d - b c \equiv 0 \pmod{p}$$。 由于 $$a, b, c, d < \sqrt{p}$$,显然 $$a d < p$$ 且 $$b c < p$$,所以 $$|a d - b c| < p$$。 因此 $$a d - b c = 0, a/b = c/d$$。 设 $$a/b \equiv -c/d \pmod{p}$$,容易得到 $$a d + b c \equiv 0 \pmod{p}$$。 由于 $$0 < a, b, c, d < \sqrt{p}$$,我们有 $$0 < a d + b c < 2p$$,所以 $$a d + b c = p$$。 发挥一下注意力,我们有: $$ \begin{aligned} (a d + b c)^2 + (a c - b d)^2&= a^2 d^2 + 2 a b c d + b^2 c^2 + a^2 c^2 - 2 a b c d + b^2 d^2\\ &= a^2 (c^2 + d^2) + b^2 (c^2 + d^2)\\ &= (a^2 + b^2)(c^2 + d^2)\\ &= p^2 \end{aligned} $$ 由于 $$a d + b c = p$$,我们有 $$p^2 + (a c - b d)^2 = p^2$$,因此 $$a c - b d = 0, a c = b d$$,我们得到 $$a/b = d/c$$,这与早些时候得到的 $$a/b = c/d$$ 似乎本质相同($c,d$ 顺序无关),放在一起讨论。 设 $$k = a/b = d/c$$,则 $$a = k b$$ 且 $$d = k c$$。代入 $$a^2 + b^2 = p$$ 得到 $$k^2 b^2 + b^2 = b^2 (k^2 + 1) = p$$。类似地有 $$c^2 + k^2 c^2 = c^2 (k^2 + 1) = p$$。 因此,$$b^2 (k^2 + 1) = c^2 (k^2 + 1)$$,从而 $$b = c$$。于是 $$a = k b = k c$$ 且 $$d = k c = k b$$,所以 $$a = d$$,因此 $$\{a, b\} = \{c, d\}$$。 综上,$$p$$ 表示为两个平方数之和的表示在无序意义下是唯一的。 ::::

那么就简单了,每个质数写成高斯整数之后,只有一种本质不同的表示方法,顶多交换一下两个维度。直接对着搜索,枚举两类表示方法分别出现了几次,复杂度就是对的。

当然了,答案的两维也可以交换,如果担心漏解了,可以加上这一步,然后再去重。

除此之外再次强调,一堆复数乘起来可能有负的,记得取绝对值。使用 128 位整数来防止乘法导致的溢出。

给出一份参考代码,去除了宏定义与缺省源,它的语义应该比较明确,可以当作伪代码读。

时间复杂度,由于我数论不太行,可能只能分析到 \log^2 级别,不过仍旧是够用的,主要是我不知道一些数值应该用什么符号。据我观察,另一篇题解似乎与这个解法本质相同,复杂度也应该类似吧。

实践上跑得挺快。

struct cpx{
    i128 x,y;
    cpx(i128 p=0,i128 q=0){x=p,y=q;}
    void operator=(const i128&p){*this={p,0};}
    cpx operator*(const cpx&c)const{
        return cpx(x*c.x-y*c.y,x*c.y+y*c.x);
    }
};//复数类
template<class T>
T q_pow(T a,ll b){
    T res;
    for(res=1;b;b>>=1,a=a*a)
        if(b&1)res=res*a;
    return res;
}
i128 _abs(i128 a){
    return a>=0?a:-a;
}
void dfs(int i,cpx res,const vector<pair<cpx,int>>&vt,vector<cpx>&ret){
    if(i==(int)vt.size()){
        res.x=_abs(res.x),
        res.y=_abs(res.y),
        ret.push_back(res),
        swap(res.x,res.y),
        ret.push_back(res);
        return;
    }
    vector<cpx>p0;
    cpx it=vt[i],vl=1;
    for(int c=0;c<=vt[i].y;c++,vl=vl*it)
        p0.push_back(vl);
    swap(it.x,it.y),vl=1;
    for(int c=0;c<=vt[i].y;c++,vl=vl*it)
        //枚举:有 c 个高斯整数交换了两维,而 vt[i].y-c 个没有交换
        dfs(i+1,res*p0[vt[i].y-c]*vl,vt,ret);
}
pair<ll, ll> Cornacchia(const ll& P, ll p, ll t, ll d);//等下给出完整实现
signed main(){
    for(cin(T);T;T--){
        cin(n);
        vector<ll>d=PollardRho::factor(n);//质因数分解
        __gnu_pbds::gp_hash_table<ll,int>mp;
        for(ll&pr:d)mp[pr]++;
        if([&]()->bool{
            for(auto[v,t]:mp)
                if(v%4==3&&t%2==1)return 1;
            return 0;
        }()){
            puts("0");
            continue;
        }
        cpx res=1;
        vector<cpx>ret;
        vector<pair<cpx,int>>vt;
        for(auto[v,t]:mp){
            if(v==2)
                res=res*q_pow(cpx(1,1),t);//其实理论上直接加入 vt 也是对的,交换两个 1 不会得到错的解,但还是稍微精细一点好了
            else if(v%4==3)
                vt.push_back({cpx(v,0),t/2});
            else{
                ll I=Cipolla::getI(v);//求 v-1 也就是 -1 的二次剩余
                pair<ll,ll> w=Cornacchia(v,v,I,1);
                vt.push_back({cpx(w.x,w.y),t});
            }
        }
        dfs(0,res,vt,ret);
        auto cmp1=[&](cpx a,cpx b){
            return tie(a.x,a.y)<tie(b.x,b.y);
        };
        auto cmp2=[&](cpx a,cpx b){
            return tie(a.x,a.y)==tie(b.x,b.y);
        };
        sort(all(ret),cmp1),
        ret.erase(unique(all(ret),cmp2),ret.end());
        print(ret.size()),pc('\n');
        for(auto[x,y]:ret)
            print(x),pc(' '),print(y),pc('\n');
    }
    return 0;
}

Cornacchia 算法

进入正题。

只讨论经典情形。

设我们需要求方程 x^2+d\cdot y^2 = p 的一组解 (x,y),其中 p 是奇素数且 p\nmid d,常见的特例是 d=1
算法假定模方程 t^2\equiv -d\pmod p 存在解,并断言这是原方程有解的必要条件。当 d> 1 时这个条件并不是充分的,需要额外验证。

算法流程很简单。

  1. 取一个合适的 t\in(0,p) 作为所有 t^2\equiv -d\pmod p 的解的代表。
    • 使用合适的二次剩余算法,比如 Cipolla 算法,可以很快地完成这一步。
    • 如果取了 t\in(0,p/2] 的较小的代表考虑,证明可能会稍微方便一点,但取哪个都不影响正确性。
  2. (p,t) 做辗转相除法,尝试得到一个余数序列 r,流程大概是 r_0=p,r_1=t,r_{i+1}=r_{i-1}\bmod r_i(i\ge1) 这样不断推下去,直到取到第一个足够小的余数 r_m,满足 r_{m}^2\le p
  3. x=r_m,检验 (p-x^2)/d 是否为整数,然后检验是否为完全平方数。若是,则输出解 (x,\sqrt {(p-x^2)/d}),否则报告无解。

下面是一个可行的简短示例。

using ll = long long;
pair<ll, ll> Cornacchia(const ll& P, ll p, ll t, ll d) {
    if ((__int128) t * t <= P) {
        if ((P - t * t) % d != 0)
            return make_pair(-1, -1);
        ll y = (ll)(sqrt((P - t * t) / d) + .5);
        //为避免潜在精度误差,最好手动实现一个整数平方根算法
        if (y * y * d == P - t * t) 
            return make_pair(t, y);
        else return make_pair(-1, -1); 
    }
    return Cornacchia(P, t, p % t, d);
}

值得注意的是,虽然刚刚没怎么讨论符号,但是容易看出这个实现解出来的 xy 都是非负的,我们有 0\le x,y\le \sqrt p

即使只是对于 Cornacchia 算法,复杂度瓶颈也不在上述的辗转相除上,而是在求二次剩余上。

证明

受限于时间和水平,我只能给出大概的思路和前几步,如果你有兴趣,不妨试着完整证明一遍。

欧几里得算法有一个结论。假设我们在对 (p,t) 做辗转相除,将余数序列 r 拿出来,归纳可以证明,每个余数都可以写成 r_i=A_i\cdot p+B_i\cdot t 的形式,其中 A_i,B_i\in \mathbb Z

::::info[r_i=A_i\cdot p+B_i\cdot t?] 为了方便和我一样不会数论的朋友,写一下解释。

i=0,1 可直接给出:r_0=1\cdot p+0\cdot t,r_1= 0\cdot p+1\cdot t
对更大的 i,我们有 r_{i+1}=r_{i-1}\bmod r_i=r_{i-1}-\lfloor r_{i-1}/r_i\rfloor \cdot r_i

当然也就可以递推给出

顺便可以发现,因为 $\lfloor r_{i-1}/r_i\rfloor\ge 1$,所以有些系数的绝对值有单调性。 :::: 另外还有一个比较容易得到的结论。若 $(x,y)$ 是方程 $x^2 + d\cdot y^2 = p$ 的一组非负整数解,且 $y \not \equiv 0 \pmod p$,且 $t \equiv \pm\sqrt{-d} \equiv x/y \pmod p$(这一点参考刚早些时候的证明),则存在整数 $A,B$ 使 $x = Ap+Bt$,事实上 $B = y$。 证明:由 $t \equiv x/y\pmod p$ 得 $ty \equiv x \pmod p$。因此存在整数 $k$ 使得 $ty = x + kp$,即 $x = -kp + yt$。 设 $A= −k, B= y$,得到 $x = Ap + Bt$,其中 $B=y\ge 0$。 所以我们发现,这个形式和“每个余数都可以写成 $r_i=A_i\cdot p+B_i\cdot t$ 的形式”看起来有点像。 接下来可以推出下一个结论。在所有能表示为 $Ap + Bt$ 且绝对值不大于 $t$ 的正整数中,欧几里得算法产生的余数序列恰好包含这些数,而且是按大小递减出现的。换句话说,任何形式为 $Ap+Bt$ 的数,如果满足 $0<|Ap+Bt|\le t$,必在 $r$ 序列中出现过。进而可以推出 $x$ 一定会在里面出现过。 证明需要用到连分数理论,很不幸,我不会,帮不了你。 如果你有兴趣,可以阅读论文 F. Morain, J.-L. Nicolas, "On Cornacchia's algorithm for solving the diophantine equation u^2 + dv^2 = m", 1990 研究具体证明方法。 ::::info[AI 对论文证明的解读] ## 1. 问题介绍 Cornacchia 算法用于求解如下形式的丢番图方程: $$ u^2 + d v^2 = m $$ 其中 $$d$$ 和 $$m$$ 为互质的正整数。该算法最早由意大利数学家 G. Cornacchia 在 1908 年提出,基于欧几里得算法和连分数理论。在现代密码学中,该算法在椭圆曲线素性证明中有重要应用。 ## 2. 算法描述 Cornacchia 算法的基本步骤如下: 1. **输入**:互质的正整数 $$d$$ 和 $$m$$ 2. **步骤**: - 求解同余方程 $$x^2 \equiv -d \pmod{m}$$,得到解 $$x_0$$(若不存在解,则原方程无解) - 对 $$(m, x_0)$$ 应用欧几里得算法,生成余数序列 $$r_0, r_1, \ldots, r_k$$ - 找到第一个满足 $$r_k^2 < m$$ 的余数 $$r_k$$ - 检查 $$(m - r_k^2)/d$$ 是否为完全平方数 - 若是,则 $$u = r_k, v = \sqrt{(m - r_k^2)/d}$$ 为解;否则无解 ## 3. 证明思路概述 证明的核心思想是将原问题转化为三个子问题: 1. **问题 $$\mathcal{P}$$**:求解 $$u^2 + dv^2 = m$$ 2. **问题 $$\mathcal{T}$$**(广义 Thue 问题):求互质整数 $$u, v$$ 使得 $$u + x_0v \equiv 0 \pmod{m}$$ 且满足特定界限 3. **问题 $$\mathcal{D}$$**(丢番图逼近问题):求分数 $$p/q$$ 使得 $$|qx - p| < 1/Q$$ 通过连分数理论建立这些问题之间的联系,最终证明算法的正确性。 ## 4. 详细证明 ### 4.1 问题转化(Section 2) 设 $$(u, v)$$ 是方程 $$u^2 + dv^2 = m$$ 的解,且 $$u, v$$ 互质。则有: $$ u^2 \equiv -dv^2 \pmod{m} $$ 由于 $$v$$ 与 $$m$$ 互质(因为 $$u, v$$ 互质且 $$u^2 + dv^2 = m$$),可得: $$ (u/v)^2 \equiv -d \pmod{m} $$ 令 $$x_0$$ 为模 $$m$$ 下 $$-d$$ 的平方根,即 $$x_0^2 \equiv -d \pmod{m}$$,则有: $$ u + x_0v \equiv 0 \pmod{m} \tag{1} $$ 此外,由 $$u^2 + dv^2 = m$$ 可得界限: $$ 0 < |u| < \sqrt{m}, \quad 0 < v < \sqrt{m/d} \tag{2} $$ 这就将原问题转化为**问题 $$\mathcal{T}$$**:求互质整数 $$u, v$$ 满足 (1) 和 (2)。 由 (1) 可得存在整数 $$k$$ 使得: $$ u + x_0v = km $$ 代入 (2) 得: $$ \left| v \cdot \frac{x_0}{m} - k \right| = \left| \frac{u}{m} \right| < \frac{1}{\sqrt{m}} \cdot \frac{1}{\sqrt{m/d}} = \frac{1}{\sqrt{m/d}} \tag{3} $$ 令 $$x = x_0/m, Q = \sqrt{m/d}$$,则 (3) 变为: $$ |vx - k| < \frac{1}{Q} $$ 这就转化为**问题 $$\mathcal{D}$$**:求既约分数 $$k/v$$ 使得 $$|vx - k| < 1/Q$$ 且 $$v \leq Q$$. ### 4.2 连分数理论(Section 3) 设 $$x$$ 为实数,其连分数展开为: $$ x = [a_0, a_1, a_2, \ldots] = a_0 + \frac{1}{a_1 + \frac{1}{a_2 + \cdots}} $$ 定义序列 $$p_n, q_n$$ 为: - $$p_{-2} = 0, p_{-1} = 1, p_n = a_n p_{n-1} + p_{n-2}$$ - $$q_{-2} = 1, q_{-1} = 0, q_n = a_n q_{n-1} + q_{n-2}$$ 则 $$p_n/q_n$$ 称为第 $$n$$ 个**收敛子**(convergent)。 此外,定义**中间收敛子**(intermediate convergent)为: $$ \frac{p_{n,r}}{q_{n,r}} = \frac{r p_{n+1} + p_n}{r q_{n+1} + q_n}, \quad 1 \leq r \leq a_{n+2} - 1 $$ 关键性质: 1. **行列式性质**:$$q_n p_{n-1} - p_n q_{n-1} = (-1)^{n-1}$$ 2. **逼近误差**: $$ |q_n x - p_n| = \frac{1}{a'_{n+1} q_n + q_{n-1}} < \frac{1}{q_{n+1}} $$ 其中 $$a'_n = [a_n, a_{n+1}, \ldots]$$ 3. **最佳逼近定理**:满足 $$|q x - p| < 1/(2q)$$ 的既约分数 $$p/q$$ 必为 $$x$$ 的收敛子 ### 4.3 解决 Problem $$\mathcal{D}$$(Section 4) 对于问题 $$\mathcal{D}$$:求既约分数 $$p/q$$ 使得 $$|q x - p| < 1/Q$$ 且 $$q \leq Q$$. 由最佳逼近定理,这样的分数必为 $$x$$ 的收敛子或中间收敛子。具体地: 设 $$q_n \leq Q < q_{n+1}$$,则可能的解为: - 主收敛子:$$p_n/q_n$$ - 中间收敛子:$$p_{n-1,1}/q_{n-1,1}$$ 和 $$p_{n-1,a_{n+1}-1}/q_{n-1,a_{n+1}-1}$$ 算法 `THUE(x, Q)` 如下: 1. 计算 $$x$$ 的连分数展开,直到 $$q_n \leq Q < q_{n+1}$$ 2. 令 $$r = \lfloor (Q - q_{n-1})/q_n \rfloor$$ 3. 若 $$r = 0$$,测试 $$p_{n-1}/q_{n-1}$$ 是否满足条件 4. 若 $$r \geq 1$$,测试 $$p_{n-1,r}/q_{n-1,r}$$ 是否满足条件 5. 返回所有满足条件的分数 ### 4.4 解决 Problem $$\mathcal{P}$$(Section 5) 现在回到原问题。设 $$x = x_0/m$$,$$Q = \sqrt{m/d}$$。由问题 $$\mathcal{D}$$ 的解 $$k/v$$ 可得: $$ u = km - x_0v $$ 需验证 $$u^2 + dv^2 = m$$。 **定理 5.1**:若问题 $$\mathcal{P}$$ 有解,则解为 $$u = p_n m - x_0 q_n, v = q_n$$,其中 $$q_n \leq \sqrt{m/d} < q_{n+1}$$. **证明**: 设 $$(u, v)$$ 为解,则存在 $$k$$ 使得 $$u = km - x_0v$$,且 $$k/v$$ 是问题 $$\mathcal{D}$$ 的解。由连分数理论,$$k/v$$ 是 $$x_0/m$$ 的收敛子或中间收敛子。 通过计算范数: $$ N(u,v) = u^2 + dv^2 = (km - x_0v)^2 + dv^2 $$ 利用 $$x_0^2 \equiv -d \pmod{m}$$,可得: $$ N(u,v) \equiv (k^2 + d)m^2 \pmod{m} $$ 通过细致分析收敛子和中间收敛子的性质,可以证明只有主收敛子 $$p_n/q_n$$ 能给出解。 **定理 5.2**:设 $$k$$ 为第一个满足 $$r_k^2 < m$$ 的索引,则解为 $$u = r_k, v = q_k$$. **证明**: 由欧几里得算法性质,$$r_i = m |q_i x_0/m - p_i|$$。当 $$r_k^2 < m$$ 时,有: $$ N(r_k, q_k) = r_k^2 + d q_k^2 < m + d \cdot \frac{m}{d} = 2m $$ 另一方面,由 $$u + x_0v \equiv 0 \pmod{m}$$ 可得 $$N(u,v) \equiv 0 \pmod{m}$$,故 $$N(r_k, q_k) = m$$ 或 $$2m$$。 通过分析连分数逼近误差,可排除 $$N(r_k, q_k) = 2m$$ 的情况,故 $$N(r_k, q_k) = m$$. ## 5. 总结 Cornacchia 算法通过欧几里得算法和连分数理论,高效地求解了丢番图方程 $$u^2 + dv^2 = m$$。其正确性证明依赖于将原问题转化为丢番图逼近问题,并利用连分数收敛子的最佳逼近性质。 该算法在计算数论和密码学中有重要应用,特别是椭圆曲线密码学中的素性证明。 ## 参考文献 1. G. Cornacchia, "Su di un metodo per la risoluzione in numeri interi dell' equazione ∑_{h=0}^n C_h x^{n-h} y^h = P", Giornale di Matematiche di Battaglini, 1908 2. F. Morain, J.-L. Nicolas, "On Cornacchia's algorithm for solving the diophantine equation u^2 + dv^2 = m", 1990 3. H. Cohen, "A Course in Computational Algebraic Number Theory", Springer, 1993 ::::