📅  最后修改于: 2023-12-03 15:17:18.047000             🧑  作者: Mango
给定一个正整数N,求有多少个正整数对(a,b),满足它们的最小公倍数(LCM)和最大公约数(GCD)的和等于N。
对于一个正整数对(a,b),设它们的最大公约数是d,则它们的最小公倍数是ab/d,且满足ab/d*N。因此,对于一个固定的d,我们需要求出有多少个(a,b)满足上述条件。我们称a,b互质,当且仅当它们的最大公约数d=1。
假设N的质因数分解式为N=p1^e1p2^e2...pk^ek,根据唯一分解定理,我们知道p1,p2,...,pk是N的所有质因子,e1,e2,...,ek是它们的指数。我们枚举d为N的因子,即d的质因数分解式为d=q1^f1q2^f2*...*qm^fm,其中q1,q2,...,qm是N的质因子的子集,f1,f2,...,fm是它们的指数。
首先,在d的约束下,我们需要找到有多少个互质的(a,b),这个问题很容易解决。不妨设a和b的质因数分解式分别为a=p1^x1p2^x2...pk^xk,b=p1^y1p2^y2*...*pk^yk,那么它们互质当且仅当xi和yi都为0或1。因为此时它们的最大公约数是1。
设有st个互质的正整数对(a,b),使它们的最大公约数为d。
接下来,我们要找到在d的约束下,有多少个正整数对(a,b),使它们的最小公倍数为N/d。不妨设a和b的最小公倍数是N/d,即a=b/d,那么它们的质因数分解式应满足如下两个条件:
这两个条件的含义是,除了qm之外的其它质因子所取的指数,都不能超过N的质因子分解后相应质因子的指数减去d所取的相应质因子的指数。同时,qm此时的指数应该小于等于xk。
设有Sd个符合要求的正整数对(a,b),使它们的最小公倍数为N/d。
那么,我们只需要枚举N的因数d,计算出Sd,然后根据容斥定理求出所有符合条件的(a,b)对数。即
ans = Σst * ΣSd * (-1)^{d/N}。
def factorize(N):
"""
分解N的质因数,返回每个质因数的指数。
"""
factors = {}
i = 2
while i*i <= N:
while N % i == 0:
N //= i
factors[i] = factors.get(i,0) + 1
i += 1
if N > 1:
factors[N] = 1
return factors
def count_primes(N):
"""
计算N以内的质数数量。
"""
if N <= 1:
return 0
cnt = [1] * (N+1)
cnt[0] = cnt[1] = 0
i = 2
while i*i <= N:
if cnt[i]:
j = i*i
while j <= N:
cnt[j] = 0
j += i
i += 1
return sum(cnt)
def solve(N):
"""
求有多少个正整数对(a,b),满足它们的最小公倍数和最大公约数的和等于N。
"""
factors = factorize(N)
m = len(factors)
p = list(factors.keys())
ans = 0
for mask in range(1<<m):
d = 1
for i in range(m):
if mask & (1<<i):
d *= p[i]
st = (1<<sum(factors.values())) - count_primes(d-1) - 1
Sd = 1
for i in range(m):
if mask & (1<<i):
ei = factors[p[i]]
fj = 0
for j in range(m):
if j != i and mask & (1<<j) and p[j] == p[i]:
fj = factors[p[j]]
break
Sd *= (ei - fj + 1)
ans += ((-1)**(N//d)) * st * Sd
return ans
本题解详细介绍了求解LCM和GCD之和等于N的所有可能对的计数的思路和实现方式,希望对你有所帮助。