AcWing 220. 最大公约数
原题链接
中等
作者:
皓首不倦
,
2020-09-07 14:16:24
,
所有人可见
,
阅读 455
'''
两个数x, y的最大公约数是质数
可以先枚举这个质数P,那x, y必然是P的倍数
设x = k1 * P, y = K2 * P
要让gcd(x, y) == P, 那必然需要gcd(k1, k2) = 1
能找到一对k1, k2 等价于找到了一对x y
假设K = N // P, 对于这个P而言,合法的k1, k2 数对数量
就是 K的欧拉函数*2 + K-1的欧拉函数*2 + 2的欧拉函数*2 + 1
最后的1 是 k1=1 k2=1 这个特殊数对,除了这个特殊的以外,
k1 和 k2 都是不相等的,利用欧拉函数序列的前缀和可以方便
求解这个累加值,累加所有素数P对应的累加值就是最后答案
'''
# 线性筛法筛质数同时求解1-N所有数字的欧拉函数
# ans[val] 是 val对应的欧拉函数数值
def get_eular_vals(N):
prime_vals = []
phi_vals = [0]*(N+1) # 每一个数的欧拉函数数值
phi_vals[1] = 1
flag = [True] * (N+1) # 是否是质数标记
# 下面是线性筛法选质数,每个数的欧拉函数数值被其最小的质因数更新
for val in range(2, N+1):
if flag[val]:
prime_vals.append(val)
phi_vals[val] = val-1
for p_val in prime_vals:
if val * p_val > N:
break
flag[val * p_val] = False
if val % p_val == 0:
# p_val能整除val, p_val*val 的欧拉函数相对val的欧拉函数就是多乘了一项p_val
phi_vals[val * p_val] = phi_vals[val] * p_val
break
else:
# p_val不能能整除val, p_val*val 的欧拉函数相对val的欧拉函数就是多乘了一项p_val * (1- 1/p_val)
phi_vals[val * p_val] = phi_vals[val] * (p_val-1)
return phi_vals, prime_vals
N = int(input())
eular_vals, prime_vals = get_eular_vals(N)
eular_vals[1] = 0 # 1需要特殊处理,这个问题里面需要的是每一个数小于它的且和其互质的数的个数对于1而言,这个个数是0不是1
S = eular_vals.copy() # 欧拉函数数值的前缀和
for i in range(1, len(S)):
S[i] += S[i-1]
ans = 0
for P in prime_vals:
up_bound = N // P
ans += S[up_bound] * 2 + 1 # 这边加上1是因为1*P 和 1*P 也可以形成一个特殊数对,这个数对两个值相等且都是质数,最大公约数也是质数
print(ans)