过去两天我一直在研究这个问题。我觉得我很危险;但事情并没有完全点击。希望能有一双新鲜的眼睛来完成任何建议。
任务是找出任何分母的完全减少的分数。 蛮力在一定程度上起作用,但我需要能够找到超过10 ^ 10的结果。完整的挑战在这里:
https://www.codewars.com/kata/number-of-proper-fractions-with-denominator-d/train/python
我的代码目前在哪里:
def proper_fractions(n):
if n < 1:
return 0
numbers = set(range(int(n * 0.5), 1, -1))
primes = []
while numbers:
p = numbers.pop()
primes.append(p)
numbers.difference_update(set(range(p * 2, n + 1, p)))
counter = n
for num in primes:
if n % num == 0:
counter = counter - (n//num)
n = n//num
if num >= (n ** 0.5):
break
if n == 1:
return counter
elif n > 1:
return counter - (counter // n)
答案 0 :(得分:4)
您需要计算的数字称为Euler's Totient Function,n
和1
之间n
个互译的数量。
如果n
的主要分解是:
它的欧拉函数是:
以伪代码计算它的算法:
φ = 1
m = n
- 对于小于或等于
p
的每个素数sqrt(n)
:
- 如果
m
除以p
:
- 乘以
φ
p-1
- 将
m
除以p-1
- 虽然
m
除以p
:
- 乘以
φ
p
- 将
m
除以p
- 如果
m > 1
:
- //请注意,此时
m
必须是n
大于sqrt(n)
的主要因素- 乘以
φ
m-1
答案 1 :(得分:1)
您需要的是分母提供的检查以查看gcd是否为1以及是否输出到列表然后返回该列表的长度。
def proper_fractions(n):
def gcd(x,y):
while y:
(x, y) = (y, x % y)
return x
if n <= 1:
return 0
else:
count = 0
for num in range(1,n):
denom = gcd(n,num)
if denom == 1:
count += 1
return count
答案 2 :(得分:1)
你应该使用Euler的totient函数,正如Anton用户已经说过的那样。这是解决问题的一种方法。我在代码中添加了一些注释。
def proper_fractions(n):
distinct_prime_factors = set() # use set to avoid duplicates
totient_function = n
if n == 1:
totient_function = 0
else:
i = 2
while i*i <= n:
if n % i == 0:
distinct_prime_factors.add(i)
n = n/i
else:
i += 1
if n > 1:
distinct_prime_factors.add(n) # picks up prime factors > sqrt(n)
if len(distinct_prime_factors) == 0: # empty set means denominator is prime
totient_function = n - 1
else:
for p in distinct_prime_factors:
totient_function = (totient_function*(p - 1))/p
return totient_function
Euler的totient函数使用不同的素因子。这就是为什么最好使用集合而不是列表,因为集合不允许重复元素。
此外,在while循环之后,如果n大于1,则必须在素数因子集中添加n。这是因为一旦素数因子大于n的平方根,while循环就会终止。例如,考虑数字77. while循环将拾取7,因为7 * 7 = 49,小于77.但是,它不会拾取11,因为11 * 11 = 121,大于77