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

时间:2010-01-24 12:38:33

标签: c++ algorithm if-statement

我做了这个问题[Project Euler problem 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 ++

我不知道如何使用控制结构,所以这一步

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

14 个答案:

答案 0 :(得分:19)

可被两个数字整除的最小数字是这两个数字的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 :(得分:15)

将从1到20的所有整数计入其主要因子分解因子。例如,因子18为18 = 3 ^ 2 * 2.现在,对于在1到20范围内的某个整数的素数因子分解中出现的每个素数p,找到它在所有中的最大指数那些主要的因素分析。例如,素数3将具有指数2,因为它在18的因式分解中显示为3 ^ 2,并且如果它出现在任何指数为3的素数因子分解中(即3 ^ 3) ,这个数字必须至少与3 ^ 3 = 27一样大,超出1到20的范围。现在用相应的指数收集所有这些素数,你就得到了答案。

因此,举例来说,让我们找到可以被1到4的所有数字整除的最小数字。

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

显示的素数为23。我们注意到2的最大指数为23的最大指数为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

答案 2 :(得分:10)

使用数论可以更快地解决问题。其他答案包含指示如何执行此操作。这个答案只是在原始代码中编写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)
  { ...}
}

风格不是很好,但我认为这就是你要找的东西。

答案 3 :(得分:4)

参见http://en.wikipedia.org/wiki/Greatest_common_divisor 给定两个数字a和b,你可以计算gcd(a,b),并且可被两者整除的最小数字是a * b / gcd(a,b)。显而易见的事情是保持一种运行总数,并逐一添加你关心的数字:你有一个答案到目前为止A你在下一个数字X_i中添加以考虑放

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

你可以看到这实际上是通过考虑你得到的东西,如果你将所有东西分解并将它们作为素数产品写出来的。这应该可以让你手动解决问题。

答案 4 :(得分:2)

提示:

而不是在每一步将num递增1,你可以将它递增20(将会更快地工作)。当然也可能有其他改进,如果我有时间的话,不要再考虑一下。希望我帮助你一点点。

答案 5 :(得分:1)

有问题的数字是数字1到20的最小公倍数。

因为我很懒,所以**代表取幂。设kapow(x,y)表示日志到y的基数x的整数部分。 (例如,kapow(2,8)= 3,kapow(2,9)= 3,kapow(3,9)= 2.

小于或等于20的素数是2,3,5,7,11,13和17. LCM是,

因为sqrt(20)&lt; 5,我们知道i> = 5的kapow(i,20)是1.通过检查,LCM是

  

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

  

LCM = 2 4 * 3 2 * 5 * 7 * 11 * 13 *   17 * 19

  

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

答案 6 :(得分:1)

#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;
}

该向量用于存储最小数的因子。

答案 7 :(得分:1)

JavaScript代码:

var i=1,j=1;
    
for (i = 1; ; i++) {
    for (j = 1; j <= 20; j++) {
    
        if (i % j != 0) {
            break;
        }
        if (i % j == 0 && j == 20) {
            console.log('printval' + i)
            break;
        }
    }
}

答案 8 :(得分:0)

这可以帮到你 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

答案 9 :(得分:0)

Ruby Cheat:

require 'rational'

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


lcmFinder()

答案 10 :(得分:0)

这是用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();

}

答案 11 :(得分:0)

这是@ MAK答案的C#版本,在C#中可能有List reduce方法,我在网上找到了一些东西,但没有快速示例,所以我只用了一个for循环代替Python&#39; s { {1}}:

reduce

答案 12 :(得分:0)

这就是为什么您将从编写这样的函数中受益:

long long getSmallestDivNum(long long n)
{
    long long ans = 1;
    if( n == 0)
    {
        return 0;
    }
    for (long long i = 1; i <= n; i++) 
        ans = (ans * i)/(__gcd(ans, i)); 
    return ans; 
}

答案 13 :(得分:-3)

给定最大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;