闲话:在学校不但睡不好而且甚至睡不着,睡眠时间还被新来的校长砍了,而且我没得打 WA2,我甚至还没打完 coda 篇任意一条线路,周日没有休息,恐怕要初赛后才能打。
闲话:很难说这是一个特别的算法,还是一个欧几里得辗转相除的 trick,不过我似乎没有看到一个合适的中文介绍。不论如何,它很方便地解决了我在模拟赛中遇到的问题。
一道模拟赛题
假设我们要解决这样一个问题。
给定一个正整数
2 ≤ n ≤ 10 18 2\le n\le 10^{18} 2 ≤ n ≤ 1 0 18 ,构造一组解
( a , b ) (a,b) ( a , b ) 满足
a , b a,b a , b 均为非负整数且
a 2 + b 2 = n a^2+b^2=n a 2 + b 2 = n ,或报告无解。
本题有一些和 Cornacchia 算法完全无关的做法,复杂度从四次根号到几个
log \log log 都有,但是相比之下 Cornacchia 算法可能更为通用(以及优美)。
对于这个问题,如果使用该算法,主要瓶颈在质因数分解以及二次剩余上。
首先是一些简单的推导。
“高斯整数”?以防有人像我一样不知道什么是高斯整数。
高斯整数是形如
a + b i a + bi a + bi 的复数,更准确地说,这篇文章中涉及的复数都是高斯整数。
大家知道,复数相乘时模长相乘。将问题转化一下,考虑去构造一个复数序列
w 1 ⋯ k w_{1\cdots k} w 1 ⋯ k 使得
∣ ∏ i = 1 k w i ∣ 2 = n |\prod_{i=1}^k w_i|^2=n ∣ ∏ i = 1 k w i ∣ 2 = n ,当然每个复数的实部和虚部都是非负整数。然后就只需要输出
∏ i = 1 k w i \prod_{i=1}^k w_i ∏ i = 1 k w i 的实部和虚部就可以了,记得取绝对值。
当然,上面的讨论看起来一点信息量都没有。所以先质因数分解,设
n = ∏ i = 1 c n t p i c i n=\prod_{i=1}^{cnt} p_i^{c_i} n = ∏ i = 1 c n t p i c i ,对于每个
p i p_i p i 分别构造。
p i = 2 p_i=2 p i = 2 。
令
v = 1 + i v=1+\mathrm{i} v = 1 + i 易得
∣ v ∣ 2 = 2 |v|^2=2 ∣ v ∣ 2 = 2 ,那么往
w w w 序列里插入
c i c_i c i 个
1 + i 1+\mathrm{i} 1 + i ,即可让
∣ ∏ w ∣ 2 |\prod w|^2 ∣ ∏ w ∣ 2 的值乘上
2 c i 2^{c_i} 2 c i 。
p i ≡ 3 ( m o d 4 ) p_i\equiv 3 \pmod 4 p i ≡ 3 ( mod 4 ) 。
对于 c i ≡ 0 ( m o d 2 ) c_i\equiv 0 \pmod 2 c i ≡ 0 ( mod 2 ) ,往 w w w 序列里插入 c i / 2 c_i/2 c i /2 个 p i p_i p i (注意是高斯整数 p i p_i p i ,更精确地说是 p i + 0 i p_i+0\mathrm{i} p i + 0 i )即可,每个 p i p_i p i 对 ∣ ∏ w ∣ 2 |\prod w|^2 ∣ ∏ w ∣ 2 的贡献显然是 p i 2 p_i^2 p i 2 ;
否则报告无解。
为什么无解?学过小学奥数的朋友都知道,完全平方数模
4 4 4 余
0 0 0 或
1 1 1 。
没学过也不用担心,学过抽象代数的朋友都知道,整数中模
4 4 4 余
3 3 3 的素数
p p p 在高斯域中是惯性的,
( p ) (p) ( p ) 仍然是素理想。
如果都没学过,打表找规律也不失为一个好办法。
你问我初等方法?因为
p p p 是奇数,若
p p p 是完全平方数,则
n = p n=\sqrt p n = p 是奇数。设
n = 2 k + 1 ( k ∈ N ) n=2k+1(k\in \mathbb N) n = 2 k + 1 ( k ∈ N ) ,有
n 2 = 4 k 2 + 4 k + 1 ≡ 1 ( m o d 4 ) n^2=4k^2+4k+1\equiv 1 \pmod 4 n 2 = 4 k 2 + 4 k + 1 ≡ 1 ( mod 4 ) 。
p i ≡ 1 ( m o d 4 ) p_i\equiv 1 \pmod 4 p i ≡ 1 ( mod 4 ) 。
我断言,我们可以使用 Cornacchia 算法在
O ( log 2 V ) \mathcal O(\log^2 V) O ( log 2 V ) 时间内构造一组
( a i , b i ) (a_i,b_i) ( a i , b i ) 满足
a i 2 + b i 2 = p i a_i^2+b_i^2=p_i a i 2 + b i 2 = p i ,然后往
w w w 里面插入
c i c_i c i 个
a i + i b i a_i+\mathrm{i}b_i a i + i b i 即可。根据费马平方和定理,存在满足条件的解
( a i , b i ) (a_i,b_i) ( a i , b i ) 。
当然了,实现的时候肯定要用快速幂把相等的复数先积起来,然后把所有东西乘起来。
它的正确性由过程给出。复杂度瓶颈,如前所述,在于写出高效的质因数分解和二次剩余。
P2063 二平方和定理
给定一个正整数
2 ≤ n ≤ 10 18 2\le n\le 10^{18} 2 ≤ n ≤ 1 0 18 ,求出所有非负整数数对
( a , b ) (a,b) ( a , b ) 满足
a 2 + b 2 = n a^2+b^2=n a 2 + b 2 = n 。
相比于上面那个题,这次我们需要构造所有的解。
可以发现,刚刚关于高斯整数的模型似乎仍然是适用的。
由唯一分解定理可以得到,最终仍旧得先质因数分解到每个质因子,再全部乘起来。
我们试着进一步分析看看,对于每个质数有多少种对应到高斯整数的方法,来试图遍历到所有解。
p i = 2 p_i=2 p i = 2 。
仍旧仅有
1 + i 1+\mathrm{i} 1 + i 一种可能,在实部和虚部分别枚举
0 , 1 , 2 0,1,2 0 , 1 , 2 即可得到。
p i ≡ 3 ( m o d 4 ) p_i\equiv 3 \pmod 4 p i ≡ 3 ( mod 4 ) 。
与刚刚的分析相同,必须得把
p i p_i p i 两两配对来产生若干个
p i 2 p_i^2 p i 2 的贡献。用同样的手法可以证明,只有
p i + 0 i p_i+0\mathrm i p i + 0 i 和
0 + p i i 0+p_i\mathrm i 0 + p i i 两种可能的情况。
p i ≡ 1 ( m o d 4 ) p_i\equiv 1 \pmod 4 p i ≡ 1 ( mod 4 ) 。
类似的只有两组本质相同的解
( a i , b i ) (a_i,b_i) ( a i , b i ) 和
( b i , a i ) (b_i,a_i) ( b i , a i ) (容易注意到
a i ≠ b i a_i \ne b_i a i = b i )。
引理,等一会还要用到若
( x , y ) (x,y) ( x , y ) 是方程
x 2 + d ⋅ y 2 = p x^2 + d\cdot y^2 = p x 2 + d ⋅ y 2 = p 的一组非负整数解,且
y ≢ 0 ( m o d p ) y \not \equiv 0 \pmod p y ≡ 0 ( mod p ) ,则
± − d ≡ x / y ( m o d p ) \pm\sqrt{-d} \equiv x/y \pmod p ± − d ≡ x / y ( mod p ) 。
为了方便和我一样不会数论的朋友,写一下推导。
x 2 + d ⋅ y 2 ≡ 0 ( m o d p ) x 2 ≡ − d ⋅ y 2 ( m o d p ) x 2 y 2 ≡ − d ( m o d p ) x y ≡ ± − d ( m o d 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} x 2 + d ⋅ y 2 x 2 y 2 x 2 y x ≡ 0 ≡ − d ⋅ y 2 ≡ − d ≡ ± − d ( mod p ) ( mod p ) ( mod p ) ( mod p )
证明假设存在两组不同的非负整数解
( a , b ) (a, b) ( a , b ) 和
( c , d ) (c, d) ( c , d ) ,满足
a 2 + b 2 = p a^2 + b^2 = p a 2 + b 2 = p 和
c 2 + d 2 = p c^2 + d^2 = p c 2 + d 2 = p ,且
{ a , b } ≠ { c , d } \{a, b\} \neq \{c, d\} { a , b } = { c , d } 。由于
p p p 是质数,显然
a , b , c , d a, b, c, d a , b , c , d 均为正整数。
考虑模
p p p 下的运算。由
a 2 + b 2 = p a^2 + b^2 = p a 2 + b 2 = p ,
c 2 + d 2 = p c^2 + d^2 = p c 2 + d 2 = p ,结合刚刚的讨论,
a / b a/b a / b 和
c / d c/d c / d 都是模
p p p 下
− 1 -1 − 1 的平方根。由于
p ≡ 1 ( m o d 4 ) p \equiv 1 \pmod{4} p ≡ 1 ( mod 4 ) ,
− 1 -1 − 1 的二次剩余恰好有两个互为相反数的解,
a / b ≡ ± c / d ( m o d p ) a/b \equiv \pm c/d \pmod{p} a / b ≡ ± c / d ( mod p ) 。
设
a / b ≡ c / d ( m o d p ) a/b \equiv c/d \pmod{p} a / b ≡ c / d ( mod p ) ,则
a d − b c ≡ 0 ( m o d p ) a d - b c \equiv 0 \pmod{p} a d − b c ≡ 0 ( mod p ) 。
由于
a , b , c , d < p a, b, c, d < \sqrt{p} a , b , c , d < p ,显然
a d < p a d < p a d < p 且
b c < p b c < p b c < p ,所以
∣ a d − b c ∣ < p |a d - b c| < p ∣ a d − b c ∣ < p 。
因此
a d − b c = 0 , a / b = c / d a d - b c = 0, a/b = c/d a d − b c = 0 , a / b = c / d 。
设
a / b ≡ − c / d ( m o d p ) a/b \equiv -c/d \pmod{p} a / b ≡ − c / d ( mod p ) ,容易得到
a d + b c ≡ 0 ( m o d p ) a d + b c \equiv 0 \pmod{p} a d + b c ≡ 0 ( mod p ) 。
由于
0 < a , b , c , d < p 0 < a, b, c, d < \sqrt{p} 0 < a , b , c , d < p ,我们有
0 < a d + b c < 2 p 0 < a d + b c < 2p 0 < a d + b c < 2 p ,所以
a d + b c = p a d + b c = p a d + b c = p 。
发挥一下注意力,我们有:
( 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 \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 ) 2 + ( a c − b d ) 2 = a 2 d 2 + 2 ab c d + b 2 c 2 + a 2 c 2 − 2 ab 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 由于
a d + b c = p a d + b c = p a d + b c = p ,我们有
p 2 + ( a c − b d ) 2 = p 2 p^2 + (a c - b d)^2 = p^2 p 2 + ( a c − b d ) 2 = p 2 ,因此
a c − b d = 0 , a c = b d a c - b d = 0, a c = b d a c − b d = 0 , a c = b d ,我们得到
a / b = d / c a/b = d/c a / b = d / c ,这与早些时候得到的
a / b = c / d a/b = c/d a / b = c / d 似乎本质相同(
c , d c,d c , d 顺序无关),放在一起讨论。
设
k = a / b = d / c k = a/b = d/c k = a / b = d / c ,则
a = k b a = k b a = kb 且
d = k c d = k c d = k c 。代入
a 2 + b 2 = p a^2 + b^2 = p a 2 + b 2 = p 得到
k 2 b 2 + b 2 = b 2 ( k 2 + 1 ) = p k^2 b^2 + b^2 = b^2 (k^2 + 1) = 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 c^2 + k^2 c^2 = c^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^2 (k^2 + 1) = c^2 (k^2 + 1) b 2 ( k 2 + 1 ) = c 2 ( k 2 + 1 ) ,从而
b = c b = c b = c 。于是
a = k b = k c a = k b = k c a = kb = k c 且
d = k c = k b d = k c = k b d = k c = kb ,所以
a = d a = d a = d ,因此
{ a , b } = { c , d } \{a, b\} = \{c, d\} { a , b } = { c , d } 。
综上,
p p p 表示为两个平方数之和的表示在无序意义下是唯一的。
那么就简单了,每个质数写成高斯整数之后,只有一种本质不同的表示方法,顶多交换一下两个维度。直接对着搜索,枚举两类表示方法分别出现了几次,复杂度就是对的。
当然了,答案的两维也可以交换,如果担心漏解了,可以加上这一步,然后再去重。
除此之外再次强调,一堆复数乘起来可能有负的,记得取绝对值。使用 128 位整数来防止乘法导致的溢出。
给出一份参考代码,去除了宏定义与缺省源,它的语义应该比较明确,可以当作伪代码读。
时间复杂度,由于我数论不太行,可能只能分析到
log 2 \log^2 log 2 级别,不过仍旧是够用的,主要是我不知道一些数值应该用什么符号。据我观察,另一篇题解似乎与这个解法本质相同,复杂度也应该类似吧。
CPP 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)
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);
else if (v%4 ==3 )
vt.push_back ({cpx (v,0 ),t/2 });
else {
ll I=Cipolla::getI (v);
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 ⋅ y 2 = p x^2+d\cdot y^2 = p x 2 + d ⋅ y 2 = p 的一组解
( x , y ) (x,y) ( x , y ) ,其中
p p p 是奇素数且
p ∤ d p\nmid d p ∤ d ,常见的特例是
d = 1 d=1 d = 1 。
算法假定模方程
t 2 ≡ − d ( m o d p ) t^2\equiv -d\pmod p t 2 ≡ − d ( mod p ) 存在解,并断言这是原方程有解的必要条件。当
d > 1 d> 1 d > 1 时这个条件并不是充分的,需要额外验证。
算法流程很简单。
取一个合适的 t ∈ ( 0 , p ) t\in(0,p) t ∈ ( 0 , p ) 作为所有 t 2 ≡ − d ( m o d p ) t^2\equiv -d\pmod p t 2 ≡ − d ( mod p ) 的解的代表。
使用合适的二次剩余算法,比如 Cipolla 算法,可以很快地完成这一步。
如果取了 t ∈ ( 0 , p / 2 ] t\in(0,p/2] t ∈ ( 0 , p /2 ] 的较小的代表考虑,证明可能会稍微方便一点,但取哪个都不影响正确性。
对 ( p , t ) (p,t) ( p , t ) 做辗转相除法,尝试得到一个余数序列 r r r ,流程大概是 r 0 = p , r 1 = t , r i + 1 = r i − 1 m o d r i ( i ≥ 1 ) r_0=p,r_1=t,r_{i+1}=r_{i-1}\bmod r_i(i\ge1) r 0 = p , r 1 = t , r i + 1 = r i − 1 mod r i ( i ≥ 1 ) 这样不断推下去,直到取到第一个足够小的余数 r m r_m r m ,满足 r m 2 ≤ p r_{m}^2\le p r m 2 ≤ p 。
设 x = r m x=r_m x = r m ,检验 ( p − x 2 ) / d (p-x^2)/d ( p − x 2 ) / d 是否为整数,然后检验是否为完全平方数。若是,则输出解 ( x , ( p − x 2 ) / d ) (x,\sqrt {(p-x^2)/d}) ( x , ( p − x 2 ) / d ) ,否则报告无解。
下面是一个可行的简短示例。
CPP 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);
}
值得注意的是,虽然刚刚没怎么讨论符号,但是容易看出这个实现解出来的
x x x 和
y y y 都是非负的,我们有
0 ≤ x , y ≤ p 0\le x,y\le \sqrt p 0 ≤ x , y ≤ p 。
即使只是对于 Cornacchia 算法,复杂度瓶颈也不在上述的辗转相除上,而是在求二次剩余上。
证明
受限于时间和水平,我只能给出大概的思路和前几步,如果你有兴趣,不妨试着完整证明一遍。
欧几里得算法有一个结论。假设我们在对
( p , t ) (p,t) ( p , t ) 做辗转相除,将余数序列
r r r 拿出来,归纳可以证明,每个余数都可以写成
r i = A i ⋅ p + B i ⋅ t r_i=A_i\cdot p+B_i\cdot t r i = A i ⋅ p + B i ⋅ t 的形式,其中
A i , B i ∈ Z A_i,B_i\in \mathbb Z A i , B i ∈ Z 。
r i = A i ⋅ p + B i ⋅ t r_i=A_i\cdot p+B_i\cdot t r i = A i ⋅ p + B i ⋅ t ?为了方便和我一样不会数论的朋友,写一下解释。
对
i = 0 , 1 i=0,1 i = 0 , 1 可直接给出:
r 0 = 1 ⋅ p + 0 ⋅ t , r 1 = 0 ⋅ p + 1 ⋅ t r_0=1\cdot p+0\cdot t,r_1= 0\cdot p+1\cdot t r 0 = 1 ⋅ p + 0 ⋅ t , r 1 = 0 ⋅ p + 1 ⋅ t 。
对更大的
i i i ,我们有
r i + 1 = r i − 1 m o d r i = r i − 1 − ⌊ r i − 1 / r i ⌋ ⋅ r i r_{i+1}=r_{i-1}\bmod r_i=r_{i-1}-\lfloor r_{i-1}/r_i\rfloor \cdot r_i r i + 1 = r i − 1 mod r i = r i − 1 − ⌊ r i − 1 / r i ⌋ ⋅ r i 。
当然也就可以递推给出
A i + 1 = A i − 1 − ⌊ r i − 1 / r i ⌋ A i , B i + 1 = B i − 1 − ⌊ r i − 1 / r i ⌋ B i A_{i+1} = A_{i-1} - \lfloor r_{i-1}/r_i\rfloor A_i,B_{i+1} = B_{i-1} -\lfloor r_{i-1}/r_i\rfloor B_i A i + 1 = A i − 1 − ⌊ r i − 1 / r i ⌋ A i , B i + 1 = B i − 1 − ⌊ r i − 1 / r i ⌋ B i 。
顺便可以发现,因为
⌊ r i − 1 / r i ⌋ ≥ 1 \lfloor r_{i-1}/r_i\rfloor\ge 1 ⌊ r i − 1 / r i ⌋ ≥ 1 ,所以有些系数的绝对值有单调性。
另外还有一个比较容易得到的结论。若
( x , y ) (x,y) ( x , y ) 是方程
x 2 + d ⋅ y 2 = p x^2 + d\cdot y^2 = p x 2 + d ⋅ y 2 = p 的一组非负整数解,且
y ≢ 0 ( m o d p ) y \not \equiv 0 \pmod p y ≡ 0 ( mod p ) ,且
t ≡ ± − d ≡ x / y ( m o d p ) t \equiv \pm\sqrt{-d} \equiv x/y \pmod p t ≡ ± − d ≡ x / y ( mod p ) (这一点参考刚早些时候的证明),则存在整数
A , B A,B A , B 使
x = A p + B t x = Ap+Bt x = A p + Bt ,事实上
B = y B = y B = y 。
证明:由
t ≡ x / y ( m o d p ) t \equiv x/y\pmod p t ≡ x / y ( mod p ) 得
t y ≡ x ( m o d p ) ty \equiv x \pmod p t y ≡ x ( mod p ) 。因此存在整数
k k k 使得
t y = x + k p ty = x + kp t y = x + k p ,即
x = − k p + y t x = -kp + yt x = − k p + y t 。
设
A = − k , B = y A= −k, B= y A = − k , B = y ,得到
x = A p + B t x = Ap + Bt x = A p + Bt ,其中
B = y ≥ 0 B=y\ge 0 B = y ≥ 0 。
所以我们发现,这个形式和“每个余数都可以写成
r i = A i ⋅ p + B i ⋅ t r_i=A_i\cdot p+B_i\cdot t r i = A i ⋅ p + B i ⋅ t 的形式”看起来有点像。
接下来可以推出下一个结论。在所有能表示为
A p + B t Ap + Bt A p + Bt 且绝对值不大于
t t t 的正整数中,欧几里得算法产生的余数序列恰好包含这些数,而且是按大小递减出现的。换句话说,任何形式为
A p + B t Ap+Bt A p + Bt 的数,如果满足
0 < ∣ A p + B t ∣ ≤ t 0<|Ap+Bt|\le t 0 < ∣ A p + Bt ∣ ≤ t ,必在
r r r 序列中出现过。进而可以推出
x x x 一定会在里面出现过。
证明需要用到连分数理论,很不幸,我不会,帮不了你。
如果你有兴趣,可以阅读论文 F. Morain, J.-L. Nicolas, "On Cornacchia's algorithm for solving the diophantine equation u^2 + dv^2 = m", 1990 研究具体证明方法。
AI 对论文证明的解读1. 问题介绍 Cornacchia 算法用于求解如下形式的丢番图方程:
u 2 + d v 2 = m u^2 + d v^2 = m u 2 + d v 2 = m 其中
d d d 和
m m m 为互质的正整数。该算法最早由意大利数学家 G. Cornacchia 在 1908 年提出,基于欧几里得算法和连分数理论。在现代密码学中,该算法在椭圆曲线素性证明中有重要应用。
2. 算法描述 Cornacchia 算法的基本步骤如下:
输入 :互质的正整数 d d d 和 m m m
步骤 :
求解同余方程 x 2 ≡ − d ( m o d m ) x^2 \equiv -d \pmod{m} x 2 ≡ − d ( mod m ) ,得到解 x 0 x_0 x 0 (若不存在解,则原方程无解)
对 ( m , x 0 ) (m, x_0) ( m , x 0 ) 应用欧几里得算法,生成余数序列 r 0 , r 1 , … , r k r_0, r_1, \ldots, r_k r 0 , r 1 , … , r k
找到第一个满足 r k 2 < m r_k^2 < m r k 2 < m 的余数 r k r_k r k
检查 ( m − r k 2 ) / d (m - r_k^2)/d ( m − r k 2 ) / d 是否为完全平方数
若是,则 u = r k , v = ( m − r k 2 ) / d u = r_k, v = \sqrt{(m - r_k^2)/d} u = r k , v = ( m − r k 2 ) / d 为解;否则无解
3. 证明思路概述 证明的核心思想是将原问题转化为三个子问题:
问题 P \mathcal{P} P :求解 u 2 + d v 2 = m u^2 + dv^2 = m u 2 + d v 2 = m
问题 T \mathcal{T} T (广义 Thue 问题):求互质整数 u , v u, v u , v 使得 u + x 0 v ≡ 0 ( m o d m ) u + x_0v \equiv 0 \pmod{m} u + x 0 v ≡ 0 ( mod m ) 且满足特定界限
问题 D \mathcal{D} D (丢番图逼近问题):求分数 p / q p/q p / q 使得 ∣ q x − p ∣ < 1 / Q |qx - p| < 1/Q ∣ q x − p ∣ < 1/ Q
通过连分数理论建立这些问题之间的联系,最终证明算法的正确性。
4. 详细证明 4.1 问题转化(Section 2) 设
( u , v ) (u, v) ( u , v ) 是方程
u 2 + d v 2 = m u^2 + dv^2 = m u 2 + d v 2 = m 的解,且
u , v u, v u , v 互质。则有:
u 2 ≡ − d v 2 ( m o d m ) u^2 \equiv -dv^2 \pmod{m} u 2 ≡ − d v 2 ( mod m ) 由于
v v v 与
m m m 互质(因为
u , v u, v u , v 互质且
u 2 + d v 2 = m u^2 + dv^2 = m u 2 + d v 2 = m ),可得:
( u / v ) 2 ≡ − d ( m o d m ) (u/v)^2 \equiv -d \pmod{m} ( u / v ) 2 ≡ − d ( mod m ) 令
x 0 x_0 x 0 为模
m m m 下
− d -d − d 的平方根,即
x 0 2 ≡ − d ( m o d m ) x_0^2 \equiv -d \pmod{m} x 0 2 ≡ − d ( mod m ) ,则有:
u + x 0 v ≡ 0 ( m o d m ) (1) u + x_0v \equiv 0 \pmod{m} \tag{1} u + x 0 v ≡ 0 ( mod m ) ( 1 ) 此外,由
u 2 + d v 2 = m u^2 + dv^2 = m u 2 + d v 2 = m 可得界限:
0 < ∣ u ∣ < m , 0 < v < m / d (2) 0 < |u| < \sqrt{m}, \quad 0 < v < \sqrt{m/d} \tag{2} 0 < ∣ u ∣ < m , 0 < v < m / d ( 2 ) 这就将原问题转化为
问题 T \mathcal{T} T :求互质整数
u , v u, v u , v 满足 (1) 和 (2)。
u + x 0 v = k m u + x_0v = km u + x 0 v = km 代入 (2) 得:
∣ v ⋅ x 0 m − k ∣ = ∣ u m ∣ < 1 m ⋅ 1 m / d = 1 m / d (3) \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} v ⋅ m x 0 − k = m u < m 1 ⋅ m / d 1 = m / d 1 ( 3 ) 令
x = x 0 / m , Q = m / d x = x_0/m, Q = \sqrt{m/d} x = x 0 / m , Q = m / d ,则 (3) 变为:
∣ v x − k ∣ < 1 Q |vx - k| < \frac{1}{Q} ∣ vx − k ∣ < Q 1 这就转化为
问题 D \mathcal{D} D :求既约分数
k / v k/v k / v 使得
∣ v x − k ∣ < 1 / Q |vx - k| < 1/Q ∣ vx − k ∣ < 1/ Q 且
v ≤ Q v \leq Q v ≤ Q .
4.2 连分数理论(Section 3) x = [ a 0 , a 1 , a 2 , … ] = a 0 + 1 a 1 + 1 a 2 + ⋯ x = [a_0, a_1, a_2, \ldots] = a_0 + \frac{1}{a_1 + \frac{1}{a_2 + \cdots}} x = [ a 0 , a 1 , a 2 , … ] = a 0 + a 1 + a 2 + ⋯ 1 1 定义序列
p n , q n p_n, q_n p n , q n 为:
p − 2 = 0 , p − 1 = 1 , p n = a n p n − 1 + p n − 2 p_{-2} = 0, p_{-1} = 1, p_n = a_n p_{n-1} + p_{n-2} 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 q_{-2} = 1, q_{-1} = 0, q_n = a_n q_{n-1} + q_{n-2} q − 2 = 1 , q − 1 = 0 , q n = a n q n − 1 + q n − 2
则
p n / q n p_n/q_n p n / q n 称为第
n n n 个
收敛子 (convergent)。
此外,定义中间收敛子 (intermediate convergent)为:
p n , r q n , r = r p n + 1 + p n r q n + 1 + q n , 1 ≤ r ≤ a n + 2 − 1 \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 q n , r p n , r = r q n + 1 + q n r p n + 1 + p n , 1 ≤ r ≤ a n + 2 − 1 关键性质:
行列式性质 :q n p n − 1 − p n q n − 1 = ( − 1 ) n − 1 q_n p_{n-1} - p_n q_{n-1} = (-1)^{n-1} q n p n − 1 − p n q n − 1 = ( − 1 ) n − 1
逼近误差 :
∣ q n x − p n ∣ = 1 a n + 1 ′ q n + q n − 1 < 1 q n + 1 |q_n x - p_n| = \frac{1}{a'_{n+1} q_n + q_{n-1}} < \frac{1}{q_{n+1}} ∣ q n x − p n ∣ = a n + 1 ′ q n + q n − 1 1 < q n + 1 1
其中 a n ′ = [ a n , a n + 1 , … ] a'_n = [a_n, a_{n+1}, \ldots] a n ′ = [ a n , a n + 1 , … ]
最佳逼近定理 :满足 ∣ q x − p ∣ < 1 / ( 2 q ) |q x - p| < 1/(2q) ∣ q x − p ∣ < 1/ ( 2 q ) 的既约分数 p / q p/q p / q 必为 x x x 的收敛子
4.3 解决 Problem D \mathcal{D} D (Section 4) 对于问题
D \mathcal{D} D :求既约分数
p / q p/q p / q 使得
∣ q x − p ∣ < 1 / Q |q x - p| < 1/Q ∣ q x − p ∣ < 1/ Q 且
q ≤ Q q \leq Q q ≤ Q .
由最佳逼近定理,这样的分数必为
x x x 的收敛子或中间收敛子。具体地:
设
q n ≤ Q < q n + 1 q_n \leq Q < q_{n+1} q n ≤ Q < q n + 1 ,则可能的解为:
主收敛子:p n / q n p_n/q_n p n / q n
中间收敛子:p n − 1 , 1 / q n − 1 , 1 p_{n-1,1}/q_{n-1,1} p n − 1 , 1 / q n − 1 , 1 和 p n − 1 , a n + 1 − 1 / q n − 1 , a n + 1 − 1 p_{n-1,a_{n+1}-1}/q_{n-1,a_{n+1}-1} p n − 1 , a n + 1 − 1 / q n − 1 , a n + 1 − 1
算法 THUE(x, Q) 如下:
计算 x x x 的连分数展开,直到 q n ≤ Q < q n + 1 q_n \leq Q < q_{n+1} q n ≤ Q < q n + 1
令 r = ⌊ ( Q − q n − 1 ) / q n ⌋ r = \lfloor (Q - q_{n-1})/q_n \rfloor r = ⌊( Q − q n − 1 ) / q n ⌋
若 r = 0 r = 0 r = 0 ,测试 p n − 1 / q n − 1 p_{n-1}/q_{n-1} p n − 1 / q n − 1 是否满足条件
若 r ≥ 1 r \geq 1 r ≥ 1 ,测试 p n − 1 , r / q n − 1 , r p_{n-1,r}/q_{n-1,r} p n − 1 , r / q n − 1 , r 是否满足条件
返回所有满足条件的分数
4.4 解决 Problem P \mathcal{P} P (Section 5) 现在回到原问题。设
x = x 0 / m x = x_0/m x = x 0 / m ,
Q = m / d Q = \sqrt{m/d} Q = m / d 。由问题
D \mathcal{D} D 的解
k / v k/v k / v 可得:
u = k m − x 0 v u = km - x_0v u = km − x 0 v 需验证
u 2 + d v 2 = m u^2 + dv^2 = m u 2 + d v 2 = m 。
定理 5.1 :若问题
P \mathcal{P} P 有解,则解为
u = p n m − x 0 q n , v = q n u = p_n m - x_0 q_n, v = q_n u = p n m − x 0 q n , v = q n ,其中
q n ≤ m / d < q n + 1 q_n \leq \sqrt{m/d} < q_{n+1} q n ≤ m / d < q n + 1 .
证明 :
设
( u , v ) (u, v) ( u , v ) 为解,则存在
k k k 使得
u = k m − x 0 v u = km - x_0v u = km − x 0 v ,且
k / v k/v k / v 是问题
D \mathcal{D} D 的解。由连分数理论,
k / v k/v k / v 是
x 0 / m x_0/m x 0 / m 的收敛子或中间收敛子。
通过计算范数:
N ( u , v ) = u 2 + d v 2 = ( k m − x 0 v ) 2 + d v 2 N(u,v) = u^2 + dv^2 = (km - x_0v)^2 + dv^2 N ( u , v ) = u 2 + d v 2 = ( km − x 0 v ) 2 + d v 2 利用
x 0 2 ≡ − d ( m o d m ) x_0^2 \equiv -d \pmod{m} x 0 2 ≡ − d ( mod m ) ,可得:
N ( u , v ) ≡ ( k 2 + d ) m 2 ( m o d m ) N(u,v) \equiv (k^2 + d)m^2 \pmod{m} N ( u , v ) ≡ ( k 2 + d ) m 2 ( mod m ) 通过细致分析收敛子和中间收敛子的性质,可以证明只有主收敛子
p n / q n p_n/q_n p n / q n 能给出解。
定理 5.2 :设
k k k 为第一个满足
r k 2 < m r_k^2 < m r k 2 < m 的索引,则解为
u = r k , v = q k u = r_k, v = q_k u = r k , v = q k .
证明 :
由欧几里得算法性质,
r i = m ∣ q i x 0 / m − p i ∣ r_i = m |q_i x_0/m - p_i| r i = m ∣ q i x 0 / m − p i ∣ 。当
r k 2 < m r_k^2 < m r k 2 < m 时,有:
N ( r k , q k ) = r k 2 + d q k 2 < m + d ⋅ m d = 2 m N(r_k, q_k) = r_k^2 + d q_k^2 < m + d \cdot \frac{m}{d} = 2m N ( r k , q k ) = r k 2 + d q k 2 < m + d ⋅ d m = 2 m 另一方面,由
u + x 0 v ≡ 0 ( m o d m ) u + x_0v \equiv 0 \pmod{m} u + x 0 v ≡ 0 ( mod m ) 可得
N ( u , v ) ≡ 0 ( m o d m ) N(u,v) \equiv 0 \pmod{m} N ( u , v ) ≡ 0 ( mod m ) ,故
N ( r k , q k ) = m N(r_k, q_k) = m N ( r k , q k ) = m 或
2 m 2m 2 m 。
通过分析连分数逼近误差,可排除
N ( r k , q k ) = 2 m N(r_k, q_k) = 2m N ( r k , q k ) = 2 m 的情况,故
N ( r k , q k ) = m N(r_k, q_k) = m N ( r k , q k ) = m .
5. 总结 Cornacchia 算法通过欧几里得算法和连分数理论,高效地求解了丢番图方程
u 2 + d v 2 = m u^2 + dv^2 = m u 2 + d v 2 = m 。其正确性证明依赖于将原问题转化为丢番图逼近问题,并利用连分数收敛子的最佳逼近性质。
该算法在计算数论和密码学中有重要应用,特别是椭圆曲线密码学中的素性证明。
参考文献
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
F. Morain, J.-L. Nicolas, "On Cornacchia's algorithm for solving the diophantine equation u^2 + dv^2 = m", 1990
H. Cohen, "A Course in Computational Algebraic Number Theory", Springer, 1993