Наименьшее число, которое делится на все числа от 1 до 20?

Я сделал эту проблему [задача проекта Эйлера 5], но очень плохой способ программирования, см. код на c++,

#include<iostream>
using namespace std;
// to find lowest divisble number till 20

int main()
{
int num = 20, flag = 0;

while(flag == 0)
{
    if ((num%2) == 0 && (num%3) == 0 && (num%4) == 0    && (num%5) == 0 && (num%6) == 0 
    && (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) ==0   
    && (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18)==0
    && (num%19) == 0    && (num%20) == 0)       

    {
        flag =  1;
        cout<< " lowest divisible number upto 20 is  "<< num<<endl;
    }

    num++;
}

}

я решал это на c++ и застрял в цикле, как бы решить этот шаг......

  • рассмотрим num = 20 и разделим его на числа от 1 до 20
  • проверить, все ли остатки равны нулю,
  • если да, закройте и покажите выход num
  • или еще num++

i не знаю, как использовать структуры управления, так что этот шаг

if ((num%2) == 0 && (num%3) == 0 && (num%4) == 0    && (num%5) == 0 && (num%6) == 0 
&& (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) ==0   
&& (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18)==0
&& (num%19) == 0    && (num%20) == 0) `

как правильно закодировать это?

ответ на эту проблему:

abhilash@abhilash:~$ ./a.out 
 lowest divisible number upto 20 is  232792560

12 ответов


существует более быстрый способ ответить на проблему, используя теорию чисел. Другие ответы содержат указания, как это сделать. Этот ответ только о лучшем способе написать if условие в исходном коде.

Если вы только хотите заменить длинное условие, вы можете выразить его более красиво в цикле for:

 if ((num%2) == 0 && (num%3) == 0 && (num%4) == 0    && (num%5) == 0 && (num%6) == 0 
&& (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) ==0   
&& (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18)==0
&& (num%19) == 0    && (num%20) == 0)     
{ ... }

будет:

{
  int divisor; 
  for (divisor=2; divisor<=20; divisor++)
    if (num%divisor != 0)
      break;
  if (divisor != 21)
  { ...}
}

стиль не очень, но я думаю, что это то, что вы искали.


наименьшее число, которое делится на два числа, является LCM из этих двух чисел. На самом деле наименьшее число делится на множество из N чисел x1..xN-это LCM этих чисел. Легко вычислить LCM двух чисел (см. статью Википедии), и вы можете расширить до N чисел, используя тот факт, что

LCM(x0,x1,x2) = LCM(x0,LCM(x1,x2))

Примечание: остерегайтесь переполнения.

код (на Python):

def gcd(a,b):
    return gcd(b,a%b) if b else a

def lcm(a,b):
    return a/gcd(a,b)*b

print reduce(lcm,range(2,21))

разложите все целые числа от 1 до 20 на их простые факторизации. Например, коэффициент 18, а 18 = 3^2 * 2. Теперь для каждого простого числа p который появляется в простой факторизации некоторого целого числа в диапазоне от 1 до 20, найдите максимальный показатель, который он имеет среди всех этих простых факторизаций. Например, prime 3 будет иметь показатель 2 потому что он появляется в факторизации 18 как 3^2, и если он появился, в каких простые множители с показателем 3 (т. е., 3^3), это число должно быть не менее 3^3 = 27, которое находится вне диапазона от 1 до 20. Теперь соберите все эти простые числа с их соответствующим показателем, и у вас есть ответ.

так, в качестве примера, давайте найдем наименьшее число делится нацело на все числа от 1 до 4.

2 = 2^1
3 = 3^1
4 = 2^2

простые числа, которые появляются 2 и 3. Отметим, что максимальный показатель 2 is 2 и максимальный показатель 3 is 1. Таким образом, наименьшее число, которое делится на все числа от 1 до 4 это 2^2 * 3 = 12.

вот относительно простая реализация.

#include <iostream>
#include <vector>

std::vector<int> GetPrimes(int);
std::vector<int> Factor(int, const std::vector<int> &);

int main() {
    int n;
    std::cout << "Enter an integer: ";
    std::cin >> n;
    std::vector<int> primes = GetPrimes(n);
    std::vector<int> exponents(primes.size(), 0);

    for(int i = 2; i <= n; i++) {
        std::vector<int> factors = Factor(i, primes);
        for(int i = 0; i < exponents.size(); i++) {
            if(factors[i] > exponents[i]) exponents[i] = factors[i];
        }
    }

    int p = 1;
    for(int i = 0; i < primes.size(); i++) {
            for(int j = 0; j < exponents[i]; j++) {
            p *= primes[i];
        }
    }

    std::cout << "Answer: " << p << std::endl;
}

std::vector<int> GetPrimes(int max) {
    bool *isPrime = new bool[max + 1];
    for(int i = 0; i <= max; i++) {
        isPrime[i] = true;
    }
    isPrime[0] = isPrime[1] = false;
    int p = 2;
    while(p <= max) {
        if(isPrime[p]) {
            for(int j = 2; p * j <= max; j++) {
                isPrime[p * j] = false;
            }
        }
        p++;
    }

    std::vector<int> primes;

    for(int i = 0; i <= max; i++) {
        if(isPrime[i]) primes.push_back(i);
    }

    delete []isPrime;
    return primes;
}

std::vector<int> Factor(int n, const std::vector<int> &primes) {
    std::vector<int> exponents(primes.size(), 0);
    while(n > 1) {
        for(int i = 0; i < primes.size(); i++) {
        if(n % primes[i] == 0) { 
        exponents[i]++;
            n /= primes[i];
        break;
        }
            }
    }
    return exponents;
}

пример вывода:

Enter an integer: 20
Answer: 232792560

см.http://en.wikipedia.org/wiki/Greatest_common_divisor Учитывая два числа a и b, вы можете вычислить gcd(a, b), а наименьшее число, делимое на оба, - a * b / gcd(a, b). Очевидная вещь, которую нужно сделать, - это сохранить своего рода бегущую сумму этого и добавить числа, которые вас волнуют один за другим: у вас есть ответ до сих пор, и вы добавляете следующее число X_i, чтобы рассмотреть, поставив

A ' = A * X_i / (gcd (A, X_i))

вы можете видеть, что это на самом деле работает, рассматривая то, что вы получаете, Если вы факторизуете все и записываете их как продукты простых чисел. Это должно в значительной степени позволить вам выработать ответ вручную.


подсказка:

вместо увеличения num на 1 на каждом шаге вы можете увеличить его на 20 (будет работать намного быстрее). Конечно, могут быть и другие улучшения, Я подумаю об этом позже, если у меня будет время. Надеюсь, я тебе немного помог.


рассматриваемое число является наименее распространенным кратным числам от 1 до 20.

потому что я ленив, пусть * * представляет экспоненциальность. Пусть kapow (x,y) представляет целочисленную часть журнала к основанию x из y. (Например, kapow(2,8) = 3, kapow(2,9) = 3, kapow (3,9) = 2.

простые числа меньше или равны 20 лет 2, 3, 5, 7, 11, 13, и 17. LCM,

поскольку sqrt(20) = 5 равно 1. Путем проверки LCM-это

LCM = 2kapow (2,20) * 3kapow(3,20) * 5 * 7 * 11 * 13 * 17 * 19

что это

LCM = 24 * 32 * 5 * 7 * 11 * 13 * 17 * 19

или

LCM = 16 * 9 * 5 * 7 * 11 * 13 * 17 * 19


#include<vector>
using std::vector;
unsigned int Pow(unsigned int base, unsigned int index);

unsigned int minDiv(unsigned int n)
{
     vector<unsigned int> index(n,0);
     for(unsigned int i = 2; i <= n; ++i)
     {
         unsigned int test = i;
         for(unsigned int j = 2; j <= i; ++j)
         {
             unsigned int tempNum = 0;
             while( test%j == 0)
             {
                 test /= j;
                 tempNum++;
             }
             if(index[j-1] < tempNum)
                 index[j-1] = tempNum;
         }
     }
     unsigned int res =1;
     for(unsigned int i = 2; i <= n; ++i)
     {
         res *= Pow( i, index[i-1]);
     }
     return res;
 }

unsigned int Pow(unsigned int base, unsigned int index)
{
    if(base == 0)
        return 0;
    if(index == 0)
        return 1;
    unsigned int res = 1;
    while(index)
    {
        res *= base;
        index--;
    }
    return res;
}

вектор используется для хранения коэффициентов наименьшего числа.


Это может помочь вам http://www.mathwarehouse.com/arithmetic/numbers/prime-number/prime-factorization.php?number=232792560

простая факторизация 232,792,560

2^4 • 3^2 • 5 • 7 • 11 • 13 • 17 • 19


Рубина Чит:

require 'rational'

def lcmFinder(a = 1, b=2)
  if b <=20
    lcm = a.lcm b
    lcmFinder(lcm, b+1)
  end
  puts a
end


lcmFinder()

это написано на c

#include<stdio.h>
#include<conio.h>
void main()
{

int a,b,flag=0;

for(a=1; ; a++)
{
    for(b=1; b<=20; b++)
    {
        if (a%b==0)
            {
                flag++;
            }

    }
    if (flag==20)
        {
            printf("The least num divisible by 1 to 20 is = %d",a);
            break;
        }
        flag=0;
}


getch();

}


вот версия c# ответа @MAK, может быть, метод сокращения списка в C#, я нашел что-то в интернете, но не быстрые примеры, поэтому я просто использовал цикл for вместо Python reduce:

static void Main(string[] args)
    {
        const int min = 2;
        const int max = 20;
        var accum = min;

        for (var i = min; i <= max; i++)
        {
            accum = lcm(accum, i);
        }

        Console.WriteLine(accum);
        Console.ReadLine();
    }

    private static int gcd(int a, int b)
    {
        return b == 0 ? a : gcd(b, a % b);
    }

    private static int lcm(int a, int b)
    {
        return a/gcd(a, b)*b;
    }

учитывая максимальное n, вы хотите вернуть наименьшее число, которое делится на 1 до 20.

давайте посмотрим на набор от 1 до 20. Во-первых, он содержит ряд простых чисел, а именно:

2
3
5
7 
11
13
17
19

Итак, поскольку он должен быть делимым на 19, Вы можете проверить только кратные 19, потому что 19-простое число. После этого вы проверяете, можно ли его разделить на тот, который ниже, и т. д. Если число можно разделить на все простые числа успешно, его можно разделить на числа от 1 до 20.

float primenumbers[] = { 19, 17, 13, 11, 7, 5, 3, 2; };

float num = 20;

while (1)
{
   bool dividable = true;
   for (int i = 0; i < 8; i++)
   {
      if (num % primenumbers[i] != 0)
      {
         dividable = false;
         break;
      }
   }

   if (dividable) { break; }
   num += 1;
}

std::cout << "The smallest number dividable by 1 through 20 is " << num << std::endl;