在给定数字的阶乘中的尾随零的数量 - Ruby

时间:2014-06-01 07:40:01

标签: ruby algorithm math factorial

尝试计算给定数字的阶乘中的尾随零的数量时遇到一些麻烦。这是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

12 个答案:

答案 0 :(得分:24)

这更像是一个数学问题。而你是对的,你走错了路。 (我的意思是你所处的道路会导致一个非常低效的解决方案)

首先尝试以数学方式减少问题。 (顺便说一句,你正在拍摄日志N阶算法。)

在我的回答中,我会尝试跳过几个步骤,因为这似乎是一个家庭作业问题。

尾随零的数量将等于系列乘法中5s的总功率。

1和n之间的数字将包含n/5n/25n/125个数字,分别是5s,25s,125s的倍数......等等。

尝试采用这些提示并提出一种算法来计算将10的权力塞进该因子中。

前方剧透

我决定在下面详细解释,如果你想尝试自己解决它然后停止阅读,试着考虑一下然后回到这里。

以下是逐步减少问题的方法

1

数字中的尾随零的数量相当于该数字因子中的10的幂

e.g。

  • 40 = 4 * 10^1并且它有1个尾随零
  • 12 = 3 * 4 * 10^0所以它有0个尾随零
  • 1500 = 3 * 5 * 10^2所以它有2个尾随零

2

因子中的数字幂10与因子中的2的幂和5的幂的最小值相同

e.g。

  • 50 = 2^1 * 5^2所以最低功率为1
  • 300 = 3^1 * 2^2 * 5^2所以最小值为2(我们只关注2和5的最小幂,所以忽略3的幂和所有其他素因子)

3

在任何阶乘中,将有比2的权力更多的2的权力

e.g。

  • 5! = 2^3 * 3^1 * 5^1
  • 10! = 2^8 * 3^4 * 5^2 * 7^1

正如你所看到的,2的功率开始增加得更快,因此5的功率将是两者的最小值。

因此我们需要做的就是计算阶乘中5的幂。

4

现在让我们关注任何n!

中5的力量
  • 4! ~ 5^0
  • 5! ~ 5^1(最多9!
  • 10! ~ 5^2(最多14!
  • 15! ~ 5^3(最高为19!)
  • 20! ~ 5^4(最多24!
  • 25! ~ 5^6(请注意从5^45^6的跳转,因为数字25会增加两个5的幂数。

5

我想在一个阶乘中计算五个总功率的方式是...计算所有5的倍数,它们都加上5的幂。然后计算所有25的倍数,它们都添加了额外的5的功率。请注意25如何增加5的两个幂,所以我可以把它作为一个幂,因为它是5的倍数和一个额外的功率,因为​​它是25的倍数。然后计算125的所有倍数({{ 1}})在阶乘乘法中,它们又增加了5的额外幂......依此类推。

6

那你怎么把它作为算法呢?

我想这个数字是5^3。所以......

  • n(向下舍入为整数)
  • pow1 = n/5
  • pow2 = n/25

依旧......

现在总功率pow3 = n/125

7

现在你能把它表达为循环吗?

答案 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 => 525, 50, 75, 100, 125)。其中,只有128/125 => 1提供了两个以上的因子,而125/(5^4) => 0以来,没有数字提供超过三个除数。因此,五个除数的总数是:

128/5 + 128/25 + 128/125 #=> 31

(请注意,对于125,其中有5的三个除数,这三个项中的每一个都计算一个; 2550等。 ,每个因子都有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)

如果N是数字,那么N中的尾随零数!是

N/5 + N/5^2 + N/5^3 ..... N/5^(m-1) WHERE (N/5^m)<1

您可以了解here此公式的来源。

答案 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