Наименьшее число, которое делится на все числа от 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;