Use a Library

Let S S be the lowest common multiple of all natural numbers from 1 to 1000 inclusive.

What is S m o d ( 1 0 9 + 7 ) S \bmod { (10^ 9+7) } ?


The answer is 849686073.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

1 solution

Prasun Biswas
Jan 2, 2016

Nice problem! I really enjoyed writing this solution. Although, I guess I missed the simpler approach (see my comment)

Denote by { p i } \{p_i\} the sequence of primes that are n \leq n and by { t i } \{t_i\} the sequence defined by t i = max { v Z + p i v n } t_i=\max\{v\in\Bbb{Z^+}\mid p_i^v\leq n\} where n n is a positive integer. I make the following claim:

Claim: LCM ( 1 , , n ) = i p i t i \textrm{LCM}(1,\ldots,n)=\large\prod_i p_i^{t_i}

Proof. Denote by { p i } \{p_i\} the sequence of primes n \leq n . By the fundamental theorem of arithmetic, every positive integer n \leq n has a unique prime representation in the primes of { p i } \{p_i\} . We consider the unique representation of k k in the primes of { p i } \{p_i\} as k = i p i q ( k , i ) k=\large\prod\limits_i p_i^{q(k,i)} for all positive integers k n k\leq n .

For the q ( k , i ) q(k,i) 's, we have the obvious lower bound 0 q ( k , i ) 1 k n 0\leq q(k,i)~\forall~1\leq k\leq n since otherwise k k will not be an integer. Now, p i q ( k , i ) n p_i^{q(k,i)}\leq n if q ( k , i ) t i q(k,i)\leq t_i but if q ( k , i ) > t i q(k,i)\gt t_i for some k k , then k > n k\gt n by definition of t i t_i , so we also have the upper bound q ( k , i ) t i 1 k n q(k,i)\leq t_i~\forall~1\leq k\leq n . So, we have,

0 q ( i , k ) t i 1 k n (1) 0\leq q(i,k)\leq t_i~\forall~1\leq k\leq n\tag1

Now, we use the definition of LCM ( a , b ) \textrm{LCM}(a,b) for positive integers a , b a,b with prime representations a = i p i a i a=\prod\limits_i p_i^{a_i} and b = i p i b i b=\prod\limits_i p_i^{b_i} which is,

LCM ( a , b ) = i p i max ( a i , b i ) \textrm{LCM}(a,b)=\large\prod_i p_i^{\max(a_i,b_i)}

This definition easily extends to LCM \textrm{LCM} of first n n positive integers as,

LCM ( 1 , , n ) = i p i max 1 k n q ( k , i ) \textrm{LCM}(1,\ldots,n)=\large\prod_i p_i^{\displaystyle\max\limits_{1\leq k\leq n}q(k,i)}

By ( 1 ) (1) , this reduces to,

LCM ( 1 , , n ) = i p i t i \textrm{LCM}(1,\ldots,n)=\large\prod_i p_i^{t_i}

which proves the above claim, and we're done. _\square .


Now that the above claim has been proved, we implement it in a python code to compute our required lcm. Here's the code in python 3 :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def lcm_upto_n(n):
    lcm=1
    mylist=[0]*(n+1)
    for i in range(2,n+1):
        if mylist[i]==0:
            tmp=i
            while(tmp*i<=n):
                tmp*=i
            lcm*=tmp
            for j in range(i,n+1,i):
                mylist[j]='n'
    return lcm



lcm=lcm_upto_n(int(input('LCM of first ? positive integers = ')))
print('\nRequired LCM modulo 10^9+7 is',lcm%(10**9+7))

Output of the above code (with input n = 1000 n=1000 ) :

LCM of first ? positive integers = 1000

Required LCM modulo 10^9+7 is 849686073

Explanation for the code : In the function lcm_upto_n() , I implemented the Sieve of Eratosthenes to find out the primes n \leq n and then, for each prime found, I compute the highest power of that prime that is n \leq n . After the highest power of a prime is found, I multiply it with the value of lcm stored before (starting out with lcm =1) and proceed onto finding the next prime. In this way, all the highest prime powers n \leq n are multiplied one by one till this is done for all the primes n \leq n .

This is the required LCM (according to the claim proved at the beginning of this solution) which is then returned by the function.


Here 's a copy of the above code written in Python 3 at Ideone, in case the solution reader wants to fork and test the code by themselves online.

Here 's the C++ equivalent of the above code at Ideone. Making a few technical changes would easily give the reader the C equivalent of this code too.

Moderator note:

Good approach for thinking of it directly as a combined LCM.

Like you mentioned, in the comments you show a version which uses the fact about GCD's, and hence avoids explicitly having to find the list of primes. I believe that the order complexity would be much lower in this case.

Maybe a simpler approach would be to just use the Euclidean Algorithm...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def gcd(a,b):
    return a if b==0 else gcd(b,a%b)
def lcm(a,b):
    return (a*b)//gcd(a,b)

n=int(input('LCM of first ? positive integers = '))
t=1
for i in range(2,n+1):
    t=lcm(t,i)
print('\nRequired LCM modulo 10^9+7 is',t%(10**9+7))

Prasun Biswas - 5 years, 5 months ago

Log in to reply

It's really nice to hear that you enjoyed solving the problem.

I used euclidean algorithm too and my code is similar to yours. However, a loop can be used instead of recursion to speed up the process.

1
2
3
4
5
def lcm(a, b):
    product = a * b
    while b:
        a, b = b, a%b
    return product / a

Your maximum prime exponent approach is really amazing and it probably many times faster than euclidean approach. Good job!

Arulx Z - 5 years, 5 months ago

It's funny to see how the whole code can be written in 2 lines with python -

1
2
3
>>> from fractions import gcd
>>> reduce(lambda x, y : (x * y) / gcd(x, y), range(1, 1001)) % (10 ** 9 + 7)
849686073L

Note: this may not work in Python 3
Arulx Z - 5 years, 5 months ago

Log in to reply

Wow, this is nice! I've seen usage of lambda and reduce in a few python codes. It does make the code concise and elegant.

I have yet to read about it though. Regarding your note, I googled around and it seems that it works in Python 3 with just a little modification of your code. :)

1
2
3
>>> from functools import reduce; from fractions import gcd
>>> reduce(lambda x,y:(x*y)//gcd(x,y),range(1,1001))%(10**9+7)
849686073

Prasun Biswas - 5 years, 5 months ago

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;
const unsigned int M = 1000000007;
long long int lcm(long long int a,long long int b)
{   long long int c,a1,b1;
    a1=a;   
    b1=b;
    while(b!=0)
    {  c=a;
       a=b;
       b=c%b;
    }
    return a1*(b1/a);
}
long long int rlcm(long long int f,long long int l)
{    long long int c=f+1;
    for(;c<=l;c++)
    {
        f=lcm(f,c);
    }

    return f;
}
int main(){
    int n;
    cin>>n; //N Is 1000 for this question
    cout<<rlcm(1,n)%M;
    return 0;
}

So I made a C++ program using same approach, but it gives wrong answers when 'n' (Upto which LCM is calculated) gets large The output I get is 274119074, What should I do to make it correct? Seems like everyone here used python which handles large numbers well.

Gaurav Bholla - 5 years, 5 months ago

Log in to reply

Seems like you need to use a library to handle large numbers. However, for this question, there's a better approach although the approach wasn't intended. You can take up Prasun's max prime power approach and then use modular arithmetic to simplify the answer at every step. This way, you can avoid overflow.

Arulx Z - 5 years, 5 months ago

Like Arulx mentioned, since there's no native C++ datatype to store such large numbers properly, you'd need to use an external library capable of performing arbitrary-precision arithmetic if you want to follow with the Euclidean Algorithm approach. I'd recommend using cpp_int from boost/multiprecision/cpp_int.hpp with the boost::multiprecision namespace in your code and Boost library (and a C++ compiler, of course) installed in your PC.

Here 's a slightly modified version of your code (at Ideone) using the boost library. Compiling and executing it with input n=1000 does give the correct answer.

This is exactly why I usually avoid using C/C++ for problems that require storing and performing calculations on very large numbers.

Then again, as Arulx mentioned, for this particular problem, you can avoid the Euclidean algorithm approach completely and instead use the algorithm described in my posted solution along with simplifying the result by performing the modular operation at every step so as to avoid overflow/loss of precision. Here 's the C++ code for that (I assume you're familiar with the new operator in C++, since I used that in this code).

Prasun Biswas - 5 years, 5 months ago

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...