前天晚上微信群里有群友提出了一个问题:

对于一个任意整数N>100,求一个近似算法,使得N=a×b+c(其中a,b,c都是非负整数),并且令a+b+c尽量地小。

初看这道题,笔者第一感觉就是“这还需要算法?”,因为看上去自由度太大了,应该能求出个解析解才对,于是简单分析了一下之后就给出了个“答案”,结果很快就有群友给出了反例。这时,笔者才意识到这题并非那么平凡,随后正式推导了一番,总算得到了一个可行的算法。正当笔者以为这个问题已经结束时,另一个数学群的群友精妙地构造了新的参数化,证明了算法的复杂度还可以进一步下降!

整个过程波澜起伏,让笔者获益匪浅,遂将过程记录在此,与大家分享。

随手的错 #

抛开N>100这个约束,将原问题可以等价变换为:

已知a,bN,abN,求S=Nab+a+b的最小值。

很明显当N足够大时,ab应该占主项,所以直觉上就是ab尽量接近Na,b尽可能向相等,于是就随手拍了个“a=b=Na=N,b=N+1”二选一的答案。然而很快就有群友给出了反例:当N=130时,S最小值在a=10,b=13取到,而根据笔者给出的公式则是a=b=11,显然不够优。

细想之下,才发现是笔者低视这个问题了,于是乎认真推导了一番~

直接分析 #

不失一般性,设ab。首先,S可以等价变换为
S=N(ab1)2+(ab)2


可以看出,S取最小值大致上是两个方向:1、ab尽量大(接近N);2、a,b尽量接近。为此,暂且设
b=Na=Na{Na}

那么
S=Na(Na{Na})+a+Na{Na}=(a1){Na}+a+Na

考虑两个极端:

1、最理想情况下{Na}=0,那么a+Na最小值在a=N取到。

2、最不理想的情况下,{Na}可以无限接近于1,即
Sa1+a+Na=2a+Na1


此时最小值在a=N/2取到。

基于以上两点,我们就可以提出一个算法:

a遍历(N/2,N]的所有整数,令b=N/a,取S最小者。

很明显,这是一个复杂度为O(N)的算法,跟大数分解同复杂度,所以刚推导出来那会笔者对此很震惊,这个看上去不起眼的题目居然跟大数分解是同一复杂度。

新参数化 #

后来笔者将题目分享到一个数学群,经群里的大牛指点后,才发现发现自己前面的分析还是太肤浅了,原来算法的复杂度还可以明显降低。

降低复杂度的关键是引入新的参数化,并精细地放缩不等式来缩小搜索范围。假设a,b是同奇偶的,那么我们可以设a=xy,b=x+y,其中x,yN,然后得到
N+y2=x2+c,S=2x+c


新参数化的关键是将原本相乘的ab变为了相减的x2y2,从而可以更清楚地看到变化方向,并且允许更精细的放缩。如果a,b是一奇一偶,那么只需要将x换成x+12y换成y+12,推导是相似的,下面我们分别讨论。

同奇偶性 #

进一步地,我们有
S=2x+c=2x+(N+y2x2)=N+y2+1(x1)2


以及N+y2x2。如果x已经给定,那么自然是y越小S也越小。接下来又要分两种情况讨论。

第一种情况是x2N,那么y2x2N最小值显然是y=0,此时S=N+1(x1)2,很明显x越大S就越小,再结合x2N,那么最大就只能是x=N了。

第二种情况是x2N,那么y2x2N的最小值就是y=x2N,此时
S=2x+(N+y2x2)2x+[N+(x2N+1)2x2]=2x+1+2x2N


最后的式子是关于x单调递增的,所以为了让它尽可能小,那么x应该尽可能小,结合x2N,那么x=N。注意这是基于S的上界算出来的,实际S的最小值未必就在x=N取到,但我们可以利用这个结果来缩小搜索范围。代入上述不等式后,进一步得到
S2x+1+2x2N2(N+1)+1+2(N+1)2N=2N+3+21+2N

这提供了S的最小值的一个上界。假设S取最小值时x=x,c=c,那么有
S=2x+c2N+3+21+2NxN+32+1+2N=N+O(4N)

这就意味着我们只需要搜索[N,N+32+1+2N]的整数就可以找到最优解,复杂度是O(4N)而不是O(N)

一奇一偶 #

假设a,b是一奇一偶,那么我们可以设a=(x+12)(y+12),b=(x+12)+(y+12),其中x,yN,然后得到
N+(y+12)2=(x+12)2+cS=2(x+12)+c=N+(y+12)2+1(x12)2


同样要分两种情况讨论。第一,当(x+12)2N时,类似上一节的结果是y=0,x=N12。第二,当(x+12)2N时,y的最小值是y=(x+12)2N12,那么跟(7),(8)同理,代入x=N12,有
S=2(x+12)+[N+(y+12)2(x+12)2]2(x+12)+[N+((x+12)2N+1)2(x+12)2]=2(x+12)+1+2(x+12)2N2(N+1)+1+2(N+1)2N=2N+3+21+2N

因此有
S=2(x+12)+c2N+3+21+2NxN+1+1+2N=N+O(4N)

汇总结果 #

综合以上两节的结果,我们可以将求S的最小值流程整理如下:

1、如果N是平方数,那么返回x=N,y=0a=b=N,c=0);

2、否则,记录x=N,y=0x=N12+12,y=12中让S较小者;

3、遍历(N1/2,N+32+1+2N]的所有整数m,令x=m,y=m2N以及x=m+12,y=(m+12)2N12+12,如果它们对应的S更小,那么覆盖记录的x,y

4、返回a=xy,b=x+y,c=Nab

又一思路 #

文章发出后,有一位大牛觉得以上分是否同奇偶的讨论过于麻烦,于是又提出了一个新的参数化方式:令p=a+b,q=ba,那么
4Np2+q2=4c,S=p+c


注意这里p,q必须是同奇偶的,才能保证c是一个整数。

接下来的分析跟前面就几乎一样了,因为c0,所以q2p24N。考虑给定p,那么S的最小值等价于c的最小值,也等价于q的最小值。如果p24N,那么q的最小值是01,这需要根据p,q同奇偶来确定。然后根据
4S=4p+4c=4p+4Np2+q2=4N+q2+4(p2)2


所以S最小对应p最大,结合p24N则有p=2N

如果p24N,那么q的最小值是q=p24N+ε,这里ε{0,1}同样要根据p,q同奇偶来确定。然后我们代入
4S=4p+4Np2+q24p+4Np2+(p24N+ε+1)2=4p+(ε+1)2+2(ε+1)p24N


代入p=2N,我们可以得出4S的最小值的一个上界:
4S4p+(ε+1)2+2(ε+1)p24N4(2N+1)+(ε+1)2+2(ε+1)(2N+1)24N=4(2N+1)+(ε+1)2+2(ε+1)1+4N4(2N+1)+4+41+4NS2N+2+1+4N

因为S=p+cp,所以这也是p的一个上界。

综上所述,新的求S的最小值流程整理如下:

1、如果N是平方数,那么返回p=2N,q=0a=b=N,c=0);

2、否则,令p=2N,如果p是偶数,则q=0,否则q=1,计算此时的S

3、遍历(2N,2N+2+1+4N]的所有整数为p,令q=p24N+εε{0,1}来保证p,q同奇偶,如果它们对应的S更小,那么覆盖记录的p,q

4、返回a=pq2,b=p+q2,c=Nab

文章小结 #

本文分享了一道“以为是个青铜,结果是个王者”的算法题的思考和学习过程。

转载到请包括本文地址:https://spaces.ac.cn/archives/9775

更详细的转载事宜请参考:《科学空间FAQ》

如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。

如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!

如果您需要引用本文,请参考:

苏剑林. (Sep. 20, 2023). 《自然数集中 N = ab + c 时 a + b + c 的最小值 》[Blog post]. Retrieved from https://spaces.ac.cn/archives/9775

@online{kexuefm-9775,
        title={自然数集中 N = ab + c 时 a + b + c 的最小值},
        author={苏剑林},
        year={2023},
        month={Sep},
        url={\url{https://spaces.ac.cn/archives/9775}},
}