最小的正数可以被1到20的所有数字整除?

时间:2014-03-28 11:23:54

标签: python

我的代码出了什么问题?当我运行程序时,没有打印任何内容。我想要打印最小的数字,该数字可以被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    

8 个答案:

答案 0 :(得分:4)

暴力迫使这样做太慢了。您需要找出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

答案 1 :(得分:4)

蛮力:

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)

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我的看法(尽管我喜欢@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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

我尝试了这种方法,它更易于理解

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的素因数并将它们相乘。

答案 6 :(得分:0)

所以这是欧拉的问题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上的第一篇帖子/评论。

答案 7 :(得分:0)

如果仔细考虑,答案是从 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;
}