繁体   English   中英

能被 1 到 20 的所有数整除的最小正数?

[英]Smallest positive number that is evenly divisible by all of the numbers from 1 to 20?

我的代码有什么问题? 当我运行程序时,没有打印任何内容。 我想打印可以被 1 到 20 的所有数字整除的最小数字。

found = False
i = 20
while found==False:
    c = 0    # c checks if the number is the one im looking for
    for x in range(1,21):
        if i%x==0:
            c = c + 1
    if c==20: # if c = 20 then its the number im looking for
        print i
        found = True
    i = i + 1    

强制执行此操作太慢了。 你需要找出每个20以下的数的质因数是什么,然后构造包含相同数的最小数,这就是答案。

from collections import Counter

primes_below_20 = [2, 3, 5, 7, 11, 13, 17, 19]

def prime_factors(n):
    # Assume n <= 20 
    if n == 1:
        return []
    for prime in primes_below_20:
        if n % prime == 0:
            return [prime] + prime_factors(n / prime)

 primes_needed = Counter()

 for n in range(2, 21):
     primes = Counter(prime_factors(n))
     primes_needed = primes_needed | primes  # | gives the max of existing values

 total = 1
 for prime, amount in primes_needed.items():
     total *= prime ** amount

 print total

蛮力:

from itertools import count
for i in count(20):
    if all(map(lambda x: i % x == 0, range(1, 21))):
        print i
        break

非蛮力:

from itertools import count, takewhile

def primes(n):
    "Generate prime numbers up to n"
    seen = list()
    for i in xrange(2, n + 1):
        if all(map(lambda prime: i % prime, seen)):
            seen.append(i)
            yield i

def smallest(n):
    result = 1
    for prime in primes(n):
        bprime = max(takewhile(lambda x:x<=n, (prime ** c for c in count(1))))
        # we could just take last instead of max()
        result *= bprime
    return result

print smallest(20)
def is_divisible(n):
    for divisor in range(2, 21):
         if n % divisor != 0:
              return False
         return True


number = 1
while not is_divisible(number):
     number+=1
print(number)

但是,您不必检查所有数字 1..20。 如果一个数能被 20 整除,它也能被 2、5、10 整除。扩展这个,只检查 11..20 的除数就足够了。 另一件简单的事情是将候选解增加 20( number += 20 )而不是 1,因为任何其他数字都不能被 20 整除。

但是,您实际上是在寻找从 1 到 20 的数字的最小公倍数,这可以使用素数分解来完成:您将 [1, 20] 中的每个数字都写为素数的倍数,您对每个数取最大的指数素数,然后将结果相乘(手动尝试以了解它)。 这样你要找的数就是2^4 *3^2 * 5 * 7 * 11 * 13 * 17 * 19

我的看法(尽管我喜欢 @ondra 解决方案的优雅):

from collections import Counter, defaultdict

def primes(n):
    return list(x for x in range(1,n+1) 
        if all(x%y for y in range(2,x)))

primes_20 = primes(20)

def prime_factors(n):
    if n <= 0 or n < 20:
        raise ValueError
    factors = []
    while n > 1:
        for x in primes_20[1:]:
            if not n % x:
                n = n / x
                factors.append(x)
                break
    return factors

max_count = defaultdict(int)

for i in range(2,21):
    factors = prime_factors(i)
    counts = Counter(factors)
    for factor in counts:
        max_count[factor] = max(max_count[factor], counts[factor])

total = 1
for factor, count in max_count.items():
    total *= factor**count

assert any(total%x for x in range(2)) == False
print total

Ruby 中的另一个干净和快速的东西

def compute_lowest_dividing_number number
  for i in 2..(number/2)
    return i if number%i == 0
  end
  number
end

lcm = 1
n = 20
for i in 1..n
  # look ahead appraoch
  next_number = [i+1, n].min
  lcm *= compute_lowest_dividing_number(next_number) if lcm % next_number != 0
end
puts lcm

我试过这个方法,比较容易理解

i=1 
while True:
    if i%11==0 and i%12==0 and i%13==0 and i%14==0 and i%15==0 and i%16==0 and i%17==0 and i%18==0 and i%19==0 and i%20==0:
        break
    else:
        i+=1
print(i)

但这可以通过找到 11 到 20 之间的质因数并将它们相乘,以毫秒为单位完成。

所以这是欧拉问题#5。 我有那个:

#making loop for range of numbers
def rangeCount(number):
    lst = [] #using lists to see divisions
    for x in range(1, 21):
        svalue = number % x
        if svalue == 0:
            lst.append(x)
    else:
        break #Need to break to minimize computation.
return lst

number = 2520 #is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. Minimazing compute
lstpst = [] #list pasted/returned from function
while len(lstpst) < 20:
    lstpst = rangeCount(number)
    print(f"With {number} we get {lstpst}")
    number += 2 #even number must be the answer to the problem. Minimazing compute.

这是我在 StackOverflow 上的第一篇文章/评论。

如果您仔细考虑,答案是从 1 到 n 的数字的 LCM。 这是 C++ 中的代码。

#include <bits/stdc++.h>
#define IOS                         \
  ios_base::sync_with_stdio(false); \
  cin.tie(NULL);

#define ll long long int

using namespace std;

ll lcm(int n) {
  ll ans = 1;
  for (ll i = 1; i <= n; i++)
    ans = (ans * i) / (__gcd(ans, i));
  return ans;
}

int main() {
  int i;
  cin >> i;
  
  cout << lcm(i);
  
  return 0;
}

使用 Python 的最简单解决方案:

num = 21

while True:
    div = 2

    while num%div == 0 and div!=21:
        div+=1

    if div == 21:
        print(num)
        break

    num+=1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM