引理5#
设 a,b,c 都是正整数,且 a>b;令 m=⌊c/a⌋,h=(c−am)/b,k=⌊(a−1)/b⌋,c′=c−b(km+⌊h⌋),则以下递推方程成立:
N(a,b,c)=N(a−bk,b,c′)+km(m−1)/2+m⌊h⌋
证明:我们首先尝试用 N(a,b,c) 来表示 T(a,b,c) 的面积。我们不妨认为 T(a,b,c) 内部的每一个格点都代表了它左下方的单位正方形,那么 T(a,b,c) 内部的所有完整单位正方形就等于其内部的格点数,即 N(a,b,c)。然后,我们再将 T(a,b,c) 去除掉单位正方形的剩余部分以 x=i,i∈N+ 划分为 m 个梯形 Si 和一个三角形 R,如下图1所示

图1. 三角形 T(a,b,c) 的分解
然后梯形 Si 的面积就能用 (上底 + 下底) * 高 / 2 的公式表达为
∣Si∣=21[(bc−a(i−1)−⌊bc−ai⌋)+(bc−ai−⌊bc−ai⌋)]=21(ba+2{bc−ai})如下图2所示

图2. 区域Si
三角形 R 的面积则可以表示为(利用直线 ax+by=c 必定经过点 (m,h) 的性质)
∣R∣=21(ac−⌊ac⌋)bc−am=21(ac−m)h综上,我们得出等式
N(a,b,c)=∣T(a,b,c)∣−i=1∑m∣Si∣−∣R∣=2abc2−21(ac−m)h−i=1∑m21(ba+2{bc−ai})=2bcm+2hm−21i=1∑m(ba+2{bc−ai})根据上方的符号定义可知,直线 ax+by=c 必定经过点 (m,h) 和 (0,c/b);我们不难验证直线 (a−bk)x+by=c′ 必定经过点 (m,{h}) 和 (0,c′/b)。

图3. 直线 ax+by=c 和 (a-bk)x+by=c'
并且很容易证明 a−bk>0,即 a−b⌊(a−1)/b⌋>0。
此时,我们将 N(a−bk,b,c′) 带入公式可得
N(a−bk,b,c′)=2bc′m+2hm−21i=1∑m(ba−bk+2{bc′−(a−bk)i})此时有
==N(a,b,c)−N(a−bk,b,c′)2bcm−c′m+2m(h−{h})−21i=1∑m[(ba+2{bc−ai})−(ba−bk+2{bc′−(a−bk)i})]2bcm−2b(c−b(km+⌊h⌋))m+21m⌊h⌋−21i=1∑m[(ba+2{bc−ai})−(ba−k+2{bc−b(km+⌊h⌋)−(a−bk)i})]注意到这里的 {bc−b(km+⌊h⌋)−(a−bk)i} 这一复杂结构可以如下化简
{bc−b(km+⌊h⌋)−(a−bk)i}={bc−ai−(km+⌊h⌋)+ki}={bc−ai}所以
===N(a,b,c)−N(a−bk,b,c′)2(km+⌊h⌋)m+21m⌊h⌋2(km+⌊h⌋)m+21m⌊h⌋−21i=1∑m[(ba+2{bc−ai})−(ba−k+2{bc−ai})]2(km+⌊h⌋)m+21m⌊h⌋−21i=1∑mk2km(m−1)+m⌊h⌋定理2#
设 a,b,c 都是正整数,则 N(a,b,c) 可以在 O(max{loga,logb}) 的时间复杂度下计算得到。
根据引理5,令 k=⌊(a−1)/b⌋,则 a−bk 的取值有以下两种情况:
- 若 a%b=0,即 a=bt,t∈N。则 k=⌊(a−1)/b⌋=t−1,此时 a−bk=b。 当 a=b 时我们用引理4可直接求解。
- 若 a%b=0,即 a=bt+r,t∈N,r∈N+。则 k=⌊(a−1)/b⌋=t,此时 a−bk=r=a%b。
综上,递推式 N(a,b,c)=N(a−bk,b,c′)+km(m−1)/2+m⌊h⌋ 的计算复杂度等价于辗转相除法求 gcd(a,b) 的复杂度。
于是可以写出以下代码:
int64_t count_triangle(int64_t A, int64_t B, int64_t C) {
if (A == B) return m * (m - 1) / 2;
int64_t h = (C - m * A) / B;
return m * h + k * m * (m - 1) / 2 + count_triangle(B, A - B * k, C - B * (k * m + h));