【每日一题20220829】化简,求最简分数

:magic_wand: 如果 n 是分子,d 是分数的分母,当且仅当 GCD(n,d)==1,则该分数被定义为最简分数。

例如,5/16是一个最简分数,而不是6/16,因为 6 和 16 都可以被 2 整除,因此分数可以简化为3/8

现在,如果您考虑给定的数字d,那么使用d作为分母可以构建多少个最简分数?

例如,假设 d 是 15:你可以用它构建 0 和 1 之间总共 8 个不同的正确分数:1/15、2/15、4/15、7/15、8/15、11/15、13/15 和 14/15。

您将构建一个函数,该函数计算使用给定分母可以构建多少个最简分数:

proper_fractions(1)==0
proper_fractions(2)==1
proper_fractions(5)==4
proper_fractions(15)==8
proper_fractions(25)==20

ps:数字有可能会很大,使用合适的算法减少循环次数,不然计算的时间会很长,(Codewars 给定的最大的时间为12秒)。

题目难度:一般
题目来源:https://www.codewars.com/kata/55b7bb74a0256d4467000070

def proper_fractions(n: int) -> int:
    # your code here

assert proper_fractions(1) == 0
assert proper_fractions(2) == 1
assert proper_fractions(5) == 4
assert proper_fractions(15) == 8
assert proper_fractions(25) == 20
assert proper_fractions(9999999) == 6637344
assert proper_fractions(500000003) == 500000002
assert proper_fractions(1532420) == 608256
assert proper_fractions(123456789) == 82260072
assert proper_fractions(9999999999) == 5890320000

备忘:初版,实现了功能,效率不满足,后期需优化

def prime_list(n):
    plist = []
    while n != 1:
        w = 0
        for i in range(1, n + 1):
            for j in range(1, i):
                if i % j == 0:
                    w = 1
            if w == 1:
                if n % i == 0:
                    plist.append(i)
                    n = n // i
    return plist


def proper_fractions(n):
    lrsult = [i for i in range(1, n)]
    lprime = prime_list(n)
    for i in range(1, n):
        for j in lprime:
            if i % j == 0 and i in lrsult:
                lrsult.remove(i)
                break
    ll = list((set(lrsult)))
    return len(ll)

只能准确计算出前5个,后面的就不正确了,想知道解题思路和加上效率的答案

def proper_fractions(n: int) -> int:
    list1 = []
    for i in range(1,n):
        if (i % 2 == 0 and n%2 == 0) or (i % 3 == 0 and n%3==0) or (i % 5 == 0 and n%5==0):
            pass
        else:
            list1.append(i)
    print(list1)
    return len(list1)
def proper_fractions(n: int) -> int:
    prime_factor = set()
    tmp_n = n
    for i in range(2,int(math.sqrt(n))+1):
        while n%i==0:
            prime_factor.add(i)
            n //= i
    if n>1:
        prime_factor.add(n)
    prime_factor=sorted(list(prime_factor))
    res_li = []
    def inner_func(l1,ln,tmp):
        if len(tmp) == ln:
            return res_li.append(tmp)
        for i in range(len(l1)):
            inner_func(l1[i+1:],ln,tmp+[l1[i]])
    res_final=tmp_n - 1 - sum( tmp_n // prime_factor[i] - 1  for i in range(len(prime_factor)))
    for j in range(2,len(prime_factor)+1):
        inner_func(prime_factor, j, [])
        if j%2==0:
            res_final += sum(tmp_n // reduce(lambda x,y:x*y,i) -1 for i in res_li)
            res_li = []
        else:
            res_final -= sum(tmp_n // reduce(lambda x, y: x * y, i) - 1 for i in res_li)
            res_li = []
    return res_final
1 个赞

前六个能较快准确得出,后面性能就不行

def GCD(a,b):
	if a < b:
		a, b = b, a
	#  判断是否能整除,若能整除,直接返回被除数
	if a % b == 0:
		return b
	#  若不能整除,则返回函数GCD,参数做相应变化
	else:
		return GCD(b, a % b)
def proper_fractions(n: int) -> int:
	s=[1 for i in range(1,n) if GCD(i,n)==1] if n>1 else [0]
	return sum(s)

只能跑前五个,后面数字大了就跑不了了

def proper_fractions(n: int) -> int:
    s=1
    prope_set=set()
    if n==1:
        return 0
    while 1<=s<n:
        t=0
        for i in range(1,s+1):
            if s%i==0 and n%i==0:
                t+=1
        if t==1:
            prope_set.add(s)
        s+=1
    return len(prope_set)

assert proper_fractions(1) == 0
assert proper_fractions(2) == 1
assert proper_fractions(5) == 4
assert proper_fractions(15) == 8
assert proper_fractions(25) == 20
assert proper_fractions(9999999) == 6637344
assert proper_fractions(500000003) == 500000002
assert proper_fractions(1532420) == 608256
assert proper_fractions(123456789) == 82260072
assert proper_fractions(9999999999) == 5890320000