尝试计算给定数字的阶乘中的尾随零的数量时遇到一些麻烦。这是Codewars面临的挑战之一 - 无法让我通过。
zeros(12) = 2 #=> 1 * 2 * 3 .. 12 = 479001600
我认为我在这里走错路,可能有一种更优雅的红宝石方式。这就是我到目前为止所做的事情。
def zeros(n)
x = (1..n).reduce(:*).to_s.scan(/[^0]/)
return 0 if x == []
return x[-1].length if x != []
end
答案 0 :(得分:24)
这更像是一个数学问题。而你是对的,你走错了路。 (我的意思是你所处的道路会导致一个非常低效的解决方案)
首先尝试以数学方式减少问题。 (顺便说一句,你正在拍摄日志N阶算法。)
在我的回答中,我会尝试跳过几个步骤,因为这似乎是一个家庭作业问题。
尾随零的数量将等于系列乘法中5s的总功率。
1和n之间的数字将包含n/5
,n/25
,n/125
个数字,分别是5s,25s,125s的倍数......等等。
尝试采用这些提示并提出一种算法来计算将10
的权力塞进该因子中。
我决定在下面详细解释,如果你想尝试自己解决它然后停止阅读,试着考虑一下然后回到这里。
以下是逐步减少问题的方法
数字中的尾随零的数量相当于该数字因子中的10的幂
e.g。
40 = 4 * 10^1
并且它有1个尾随零12 = 3 * 4 * 10^0
所以它有0个尾随零1500 = 3 * 5 * 10^2
所以它有2个尾随零因子中的数字幂10与因子中的2的幂和5的幂的最小值相同
e.g。
50 = 2^1 * 5^2
所以最低功率为1 300 = 3^1 * 2^2 * 5^2
所以最小值为2(我们只关注2和5的最小幂,所以忽略3的幂和所有其他素因子)在任何阶乘中,将有比2的权力更多的2的权力
e.g。
5! = 2^3 * 3^1 * 5^1
10! = 2^8 * 3^4 * 5^2 * 7^1
正如你所看到的,2的功率开始增加得更快,因此5的功率将是两者的最小值。
因此我们需要做的就是计算阶乘中5的幂。
现在让我们关注任何n!
4! ~ 5^0
5! ~ 5^1
(最多9!
)10! ~ 5^2
(最多14!
)15! ~ 5^3
(最高为19!)20! ~ 5^4
(最多24!
)25! ~ 5^6
(请注意从5^4
到5^6
的跳转,因为数字25会增加两个5的幂数。我想在一个阶乘中计算五个总功率的方式是...计算所有5的倍数,它们都加上5的幂。然后计算所有25的倍数,它们都添加了额外的5的功率。请注意25如何增加5的两个幂,所以我可以把它作为一个幂,因为它是5的倍数和一个额外的功率,因为它是25的倍数。然后计算125的所有倍数({{ 1}})在阶乘乘法中,它们又增加了5的额外幂......依此类推。
那你怎么把它作为算法呢?
我想这个数字是5^3
。所以......
n
(向下舍入为整数)pow1 = n/5
pow2 = n/25
依旧......
现在总功率pow3 = n/125
现在你能把它表达为循环吗?
答案 1 :(得分:6)
所以,既然@Spunden已经如此巧妙地让猫从袋子里出来了,这就是实现它的一种方法。
<强>代码强>
def zeros(n)
return 0 if n.zero?
k = (Math.log(n)/Math.log(5)).to_i
m = 5**k
n*(m-1)/(4*m)
end
<强>实施例强>
zeros(3) #=> 0
zeros(5) #=> 1
zeros(12) #=> 2
zeros(15) #=> 3
zeros(20) #=> 4
zeros(25) #=> 6
zeros(70) #=> 16
zeros(75) #=> 18
zeros(120) #=> 28
zeros(125) #=> 31
<强>解释强>
假设n = 128
。
然后,128
可以整除的一个5^1=>5
(包括)之间的每个数字至少提供一个因子,并且有128/5 => 25
个这样的数字。其中,唯一提供多个因素的是可5^2=>25
整除的因子,其中128/25 => 5
(25, 50, 75, 100, 125
)。其中,只有128/125 => 1
提供了两个以上的因子,而125/(5^4) => 0
以来,没有数字提供超过三个除数。因此,五个除数的总数是:
128/5 + 128/25 + 128/125 #=> 31
(请注意,对于125
,其中有5
的三个除数,这三个项中的每一个都计算一个; 25
,50
等。 ,每个因子都有5
两个因子,每个因子都在第一个术语中计算。)
对于任意n
,我们首先计算最高功效k
:
5**k <= n
是:
k <= Math.log(n)/Math.log(5)
所以最大的这样的值是:
k = (Math.log(n)/Math.log(5)).to_i
正如@spundun所指出的那样,你也可以通过简单地迭代来计算k
,例如,
last = 1
(0..1.0/0).find { |i| (last *= 5) > n }
因此,因子的总数为
(n/5) + (n/25) +...+ (n/5**k)
定义:
r = 1/5,
这笔款项被视为:
n * s
,其中
s = r + r**2 +...+ r**k
s
的值是几何系列的项的总和。我忘记了那个公式,但回想一下它的来源:
s = r + r**2 +...+ r**k
sr = r**2 +...+ r**(k+1)
s-sr = r*(1-r**k)
s = r*(1-r**k)/(1-r)
然后我做了一些重新排列,以便只使用整数运算来计算结果。
答案 2 :(得分:2)
JsonIgnore
答案 3 :(得分:1)
答案 4 :(得分:0)
这是一个更容易阅读的解决方案:
def zeros(num)
char_array = num.to_s.split('')
count = 0
while char_array.pop == "0"
count += 1
end
count
end
如果您看到改进,请告诉我您的想法并随时编辑!
答案 5 :(得分:0)
关于因子及其在GanitCharcha中的尾随零的文章是有见地的,并且已经解释了这个背后的数学。看一看。
http://www.ganitcharcha.com/view-article-A-Note-on-Factorial-and-it's-Trailing-Zeros.html
答案 6 :(得分:0)
n=int(input())
j=5
c=int(0)
while int(n/j)>0:
c=c+int(n/j)
j=j*5
print(c)
答案 7 :(得分:0)
我的解决方案
def zeros(n)
trailing_zeros = []
fact = (1..n).inject(:*)
fact.to_s.split('').reverse.select {|x| break if (x.to_i != 0); trailing_zeros << x}
return trailing_zeros.count
end
答案 8 :(得分:0)
n = int (raw_input())
count = 0
num = 1
for i in xrange(n+1):
if i != 0:
num = num * i
while(num >= 10):
if num%10 == 0:
count+=1
num = num/10
else:
break
print count
答案 9 :(得分:0)
根据@spundan给出的解释,除了@ cary的代码,你可以通过非常简单有效的方式找到尾随零的数量。见下面的代码......
def zeros(n)
ret = 0
while n > 0 do
ret += n / 5
n = n/5
end
ret
end
例如零(100000000),这将为您提供输出 - &gt;的 24999999 强>
随着时间经过的时间 - &gt; 5.0453e-05 (见 5.0453e-05 )
这是偶数毫秒的一部分。
答案 10 :(得分:0)
count = 0
i =5
n = 100
k = n
while(n/i!=0):
count+=(n/i)
i=i*5
n = k
print count
答案 11 :(得分:0)
def zeros(n)
n < 5 ? 0 : (n / 5) + zeros(n / 5)
end