P33 - 判断互质

2026-09-07 00:00    #Haskell   #99题   #数论  

P33 - 判断互质

Determine whether two positive integers are coprime

官方模块:Problems.P33 核心函数:coprime


← P32 最大公约数 | P34 欧拉函数 →


题目描述

如果两个整数的最大公约数为 1,就称它们互质。互质不要求两个数本身都是素数,例如 35 和 64 互质。

函数签名

1coprime :: Integral a => a -> a -> Bool

实现

方法一:基于 GCD(最直接)

1coprime :: Integral a => a -> a -> Bool
2coprime a b = myGCD a b == 1

P32 已经完成全部计算,这道题的重点是把数学定义直接组合成程序。

方法二:不用 GCD,遍历检查公因数

1coprime :: Integral a => a -> a -> Bool
2coprime a b = null [d | d <- [2..min (abs a) (abs b)], a `mod` d == 0 && b `mod` d == 0]

直接从定义出发:不存在大于 1 的公因数。效率低但逻辑显式。

方法三:只枚举到平方根

 1coprime :: Integral a => a -> a -> Bool
 2coprime a b = all noCommonFactor [1..integerSqrt smaller]
 3  where
 4    smaller = min (abs a) (abs b)
 5    noCommonFactor divisor
 6      | smaller `mod` divisor /= 0 = True
 7      | otherwise =
 8          not (nonTrivial divisor && abs b `mod` divisor == 0)
 9          && not (nonTrivial paired && abs b `mod` paired == 0)
10      where
11        paired = smaller `div` divisor
12    nonTrivial factor = factor > 1
13
14integerSqrt :: Integral a => a -> a
15integerSqrt n = last (takeWhile (\x -> x * x <= n) [0..])

只枚举到平方根时,必须同时检查成对因子 smaller div divisor。例如 7 和 14 的公共因子 7 大于 7\sqrt 7,但它会作为因子 1 的配对项被检查到。

方法对比

方法特点效率
GCD 法一句话,最简洁O(log min(a,b))
枚举公因数从定义出发,教学直观O(min(a,b))
枚举到 √n不依赖 GCD,比方法二快O(√min(a,b))

测试

1>>> coprime 35 64
2True
3>>> coprime 21 14
4False
5>>> coprime 1 100
6True
7>>> coprime 7 14
8False

参考