← 返回编程题库
coding-gcd-of-share-lots简单免费版2000ms未尝试

份额最大公约数 — 整手再划分

GCD of Share Lots — Round-Lot Reconciliation

开始编码

跨多家执行场所的交易台维护一份「持仓 lot 大小」列表——每个场所或每个子单一个整数——并周期性地问一个问题:「能让所有腿同时清零的最大整手单位是多少?」这个单位就是各 lot 大小的最大公约数。例如场所 A 持仓 1500,B 持仓 2250,C 持仓 3750,则交易台可以以 gcd(1500, 2250, 3750) = 750 为单位平仓,每个场所恰好清零、不留零碎股。GCD 越大,过线次数越少;GCD = 1 表示各 lot 两两互素,每股都得单独报价。

请实现 solution(lots),返回 lots 中所有元素的 GCD,必须用 Stein 二进制 GCD 算法(不准用 math.gcd,不准用 %,不准用 //)。Stein 算法是 math-and-bit-tricks 的样板:用移位剥掉公共的 2 因子,用 a & -a 隔离最低置位,用「减一减、再剥 2」替代「除一除」。在没有快速除法器的硬件上(老 CPU、嵌入式固件、GPU shader)Stein 的速度优势明显;在现代 x86 上和欧几里得算法差别可忽略,但其位操作结构是经典教学算法。

把 n 元问题降为两元折叠:gcd(a, b, c, ...) = gcd(gcd(a, b), c, ...)。恒等式 gcd(x, 0) = x 同时解决空列表(返回 0)和忽略零项(零项不影响累计 gcd)。

示例

solution([]) 返回 0。空列表归约为 gcd 的单位元。

solution([42]) 返回 42。单元素列表,无需两元步骤。

solution([15, 28]) 返回 1。15 = 3·5,28 = 2²·7,无公共素因子,互素。

solution([100, 200, 350, 500]) 返回 50。每项都是 50 的倍数;100 = 2²·5²,200 = 2³·5²,350 = 2·5²·7,500 = 2²·5³ —— 公共因子是 2·5² = 50。

solution([0, 0, 0]) 返回 0。按惯例,全零的 gcd 是 0。

solution([0, 12, 0, 18]) 返回 6。零项被恒等式 gcd(x, 0) = x 吸收,答案是 gcd(12, 18) = 6。

函数骨架见 stubs/stub.py

应用背景

跨场所整手再划分是多券商执行台的日常 EOD 作业。当一个母单被切成(比如说)四个子单发到四个场所、每个子单按场所规则的整手成交——港股板块股的 board lot 是 100 / 500 / 1000 / 2000,由具体股票决定;美股名义上是 1 股 lot,但算法常按 100 股 batch;A 股则强制 100 股 board lot——日内成交一段后,每个场所的残留持仓往往有公共因子,交易台想要的是一个能同时清零所有腿的最大整手增量,下一轮扫单就可以按 K × gcd 报价、不再需要给某个场所报小数股。同一原语也出现在:(a) ETF 套利里申赎篮子的 lot 配置(创设单位必须均整除每个成分股持仓);(b) 跨币种 FX 净额结算(找到能让多腿净额归零的最小双边名义);(c) 清算所保证金抵扣计算(同时清掉多个相关期货腿的对冲单位)。Stein 算法本身——二进制 GCD——是教科书里位操作的样板写法,把 %(在没有除法器的硬件上很慢)替换为移位与减法,出现在 libgmp、OpenSSL bignum 以及大多数加密库的模运算原语里。Python 自带原生大整数除法,因此本题主要是教学性质的;但「n & -n 数尾部 0、>> 1 折半、& 1 判奇偶」这套 idiom 正是任何底层数值代码会用到的位操作模式。

约束条件

  • 0 ≤ len(lots) ≤ 10000
  • 0 ≤ lots[i] ≤ 10^9
  • 空列表返回 0
  • 单元素列表直接返回该元素
  • 全零列表返回 0
  • 零和正数混合时:零项被忽略(gcd(x, 0) = x)
  • 两元步骤必须用 Stein 二进制 GCD(不准除法 / 取模)——只能用移位、减法和奇偶判断

样例

Case 1 · canonical multi-venue example — round-lot 750

输入: [[1500,2250,3750]]

期望: 750

1500 = 2²·3·5³,2250 = 2·3²·5³,3750 = 2·3·5⁴。三者公共素因子是 2·3·5³ = 750。

Case 2 · empty list — gcd identity element is 0

输入: [[]]

期望: 0

空列表归约到 gcd 的单位元 0;约定如此,避免对一个空集合定义最大公约数的歧义。

Case 3 · single element — return as-is

输入: [[42]]

期望: 42

单元素列表的 gcd 就是该元素本身;不需要任何两元步骤。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · canonical multi-venue example — round-lot 750

输入: [[1500,2250,3750]]

期望: 750

1500 = 2²·3·5³,2250 = 2·3²·5³,3750 = 2·3·5⁴。三者公共素因子是 2·3·5³ = 750。

Case 2 · empty list — gcd identity element is 0

输入: [[]]

期望: 0

空列表归约到 gcd 的单位元 0;约定如此,避免对一个空集合定义最大公约数的歧义。

Case 3 · single element — return as-is

输入: [[42]]

期望: 42

单元素列表的 gcd 就是该元素本身;不需要任何两元步骤。