[R3C] 公因数之和

  • 难度 入门
  • 时限 1s
  • 空限 512m
  • 数论数学

数据规模:1a,b10121 \le a,b \le 10^{12}

思路

aabb 的公因数恰好是 gcd(a,b)\gcd(a,b) 的因数,所以先辗转相除求 c=gcd(a,b)c = \gcd(a,b),再枚举 i=1ci = 1 \dots \sqrt{c}:若 iicc 的因数,则 iic/ic/i 都是公因数(两者相等时只加一次),累加即可。

复杂度:时间 O(gcd(a,b))O(\sqrt{\gcd(a,b)}),空间 O(1)O(1)

仓颉实现

import std.env.*
import std.convert.*

func gcd(x: Int64, y: Int64): Int64 {
    var a = x
    var b = y
    while (b != 0) {
        let t = a % b
        a = b
        b = t
    }
    return a
}

main(): Int64 {
    let reader = getStdIn()
    let ab = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
    let a = ab[0]
    let b = ab[1]
    let c = gcd(a, b)
    var ans: Int64 = 0
    var i: Int64 = 1
    while (i * i <= c) {
        if (c % i == 0) {
            ans += i
            if (i * i != c) {
                ans += c / i
            }
        }
        i += 1
    }
    println(ans)
    return 0
}

要点:

  • a,b1012a,b \le 10^{12}ii 只需枚举到 c106\sqrt{c} \le 10^6i×ii \times iInt64 范围内不会溢出。
  • 平方数时因数 i=c/ii = c/i,只加一次。