You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:如何运用GCD、LCM公式高效解决算法问题?

嘿,我明白你为啥头疼这个围圈发巧克力的问题了——模拟法虽然直观但效率低,公式又摸不着头脑对吧?咱一步步拆解,先把问题本质搞清楚,再把公式的来龙去脉讲透,保证你下次遇到直接套公式就行!

问题回顾

n个孩子围成一圈,每隔k个孩子发放巧克力,直到选中已获得巧克力的孩子为止。已知n和k,求未获得巧克力的孩子数量nr。示例:n=12,k=9时,nr=8。

解法1:直观模拟法(适合小n场景)

如果n的数值不大,用模拟法完全没问题,思路直白到一眼就能懂:

  • 用布尔数组标记每个孩子是否已经拿到巧克力
  • 从第一个孩子开始,每次往后数k个(因为是围成一圈,所以要对n取模来循环)
  • 碰到没标记的孩子就标记为已获奖,碰到已经标记的就停止循环
  • 最后统计数组里未标记的数量就是nr

举个Python代码的例子:

def calculate_nr_simulation(n, k):
    rewarded = [False] * n
    current_idx = 0
    while True:
        if rewarded[current_idx]:
            break
        rewarded[current_idx] = True
        # 移动k步,取模n实现循环
        current_idx = (current_idx + k) % n
    return n - sum(rewarded)

# 测试示例
print(calculate_nr_simulation(12, 9))  # 输出8,符合预期

不过这种方法的短板也很明显:当n特别大(比如几万、几十万)时,循环次数会爆炸式增长,效率直接拉胯,这时候就需要高效的公式法出场了。

解法2:数学公式法(高效解决大n场景)

这个问题的本质其实和数论里的循环节有关:当你每隔k个孩子选一个时,你会形成一个固定的循环,这个循环里包含的孩子数量是有规律的。

核心公式推导

循环中能拿到巧克力的孩子数量 = n / gcd(n, k),其中gcd(n,k)是n和k的最大公约数。

那未获得巧克力的孩子数量nr就等于总人数减去循环内的人数:
nr = n - n / gcd(n, k)
也可以简化成:
nr = n * (gcd(n,k) - 1) / gcd(n,k)

为啥这个公式成立?

拿示例n=12,k=9验证:
gcd(12,9)=3,所以循环里的孩子数量是12/3=4,未获得的就是12-4=8,完全符合示例结果。

原理是:当你每隔k步移动一次时,在模n的规则下,你能走到的所有位置都是n和k最大公约数的倍数。比如gcd(12,9)=3,能走到的位置就是0、3、6、9(假设从0开始计数),正好4个,剩下的8个位置永远走不到,自然拿不到巧克力。

公式法代码实现

计算最大公约数用欧几里得算法就行,大部分编程语言都自带相关函数,比如Python的math.gcd:

import math

def calculate_nr_formula(n, k):
    g = math.gcd(n, k)
    return n - n // g

# 测试示例
print(calculate_nr_formula(12, 9))  # 输出8,正确

这个方法的计算速度是O(log(min(n,k))),不管n多大都能秒出结果,比模拟法高效太多!

总结

  • 小n场景用模拟法,直观好理解,不用费脑子记公式
  • 大n场景或者追求效率直接用公式法,核心就是求n和k的最大公约数,套公式就行

内容的提问来源于stack exchange,提问作者Snoky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:29:48