\[ \let\oldlor\lor \renewcommand{\lor}{\; \oldlor \;} \let\oldland\land \renewcommand{\land}{\; \oldland \;} \renewcommand{\set}[1]{\{\, #1 \,\}} \renewcommand{\given}{\,\mid\,} \renewcommand{\abs}[1]{\lvert #1 \rvert} \renewcommand{\divs}{\!\;\mid\;\!} \renewcommand{\ndivs}{\!\;\nmid\;\!} \renewcommand{\betw}[3][1]{#1 \leq #2 \leq #3} \renewcommand{\mod}[1]{\ (\mathrm{mod}\ #1)} \renewcommand{\floor}[1]{\left \lfloor #1 \right \rfloor} \renewcommand{\ceil}[1]{\left \lceil #1 \right \rceil} \renewcommand{\t}[1]{\texttt{#1}} \renewcommand{\fori}[2][i]{\text{for } #1 = 0, 1, \dots, #2} \renewcommand{\x}[1]{\text{#1}} \renewcommand\concat{\mathbin{+\mkern-10mu+}} \DeclareMathOperator*{\CONCAT}{\concat} \DeclareMathOperator*{\SCC}{\|} \]
UVa 10140 - Prime Distance
Time limit: 3.0 seconds
UVa Difficulty rating: 3
View on UVa
In this problem, we asked to find the closest, as well as the most distant, pairs of adjacent primes within a specified range. This range is given by two integers, L and U, where 1 <= L < U <= 2,147,483,647. You should recognize this upper bound as the maximum positive value that can fit inside a signed 32-bit integer (i.e. (2^31)-1, or INT_MAX in C++). Let's take a quick review of some definitions. A number is a prime, if and only if it is a natural number greater than 1 and has no positive divisors other than 1 and itself. Adjacent primes, as described in the problem statement, are two numbers that are both primes, but there are no other prime numbers between the adjacent primes. Note this does not mean they are necessarily adjacent in the sequence of natural numbers, rather, any two consecutive primes in a sorted list of all primes will be adjacent primes. We are asked for the closest and most distant adjacent prime pairs within a given range. We know the bounds of this range, and that its width will never exceed 1,000,000. Since the time limit for this problem is 3 seconds, and we are not given a maximum number of test cases to process, it should be clear that we will need to formulate a solution that reuses some of the work to determine the primes. So how should we compute the prime numbers contained by the given range?

Sieve of Eratosthenes

A common algorithm to determine all prime numbers between range [0..N] is the Sieve of Eratosthenes. This algorithm is a major improvement upon the naive approach, which typically involves a for-loop up to N and testing every possible divisor with the modulus operator. Basic usage of the sieve algorithm involves a boolean array of size N+1, with all elements initialized to true (except for 0 and 1, which are set to false). Then, a for-loop iteratively scans each index of the array, starting from i = 2, and if the element at index i is true (i.e. prime), an inner for-loop marks all multiples of i as false. Once the outer loop completes, the indices of all elements that are true represent the prime numbers up to N. This basic implementation typically looks something like this: We can make several improvements to this algorithm. One significant improvement involves realizing that we only need to check divisors up to sqrt(N), changing the growth rate from O(N) to O(sqrt(N)). Also, there is no need to test divisors for even numbers, since the only even prime is 2. After making the adjustments, our code now looks like the following:

Optimized Prime Testing

In order to be fast enough for large ranges, we can extend our algorithm such that optimized prime testing is used to determine primality for large numbers. Essentially, we will run the sieve with an upper bound of sqrt(INT_MAX) before processing any test cases and store the primes in a std::vector<int> as part of the sieve algorithm. When we want to determine the primality of a number larger than sqrt(N) (as above), we'll determine if N is divisible by any prime divisors <= sqrt(N), which are stored in our std::vector<int>. If the large number being tested for primality is divisible by any of the smaller primes, it is not a prime number. All we need to do is modify our sieve function to add primes to a std::vector<int> as they are discovered, and write a helper function to handle optimized prime testing.

Finishing our implementation

All that's left to do now is write rest of int main to read input, iterate over the range specified by each test case and use our isPrime helper to perform the primality test, store the primes being considered, find the closest and most distant adjacent primes, and output the result.

Links

C++ References

UVa

230 Borrowers
543 Goldbach's Conjecture
900 Brick Wall Patterns
10047 The Monocycle
10140 Prime Distance
10165 Stone Game
10338 Mischievous Children
10394 Twin Primes
10892 LCM Cardinality

CodeForces

1A Theatre Square
4A Watermelon
25A IQ test
50A Domino piling
58A Chat room
59A Word
69A Young Physicist
71A Way Too Long Words
96A Football
112A Petya and Strings
118A String Task
131A cAPS lOCK
158A Next Round
189A Cut Ribbon
230B T-primes
231A Team
263A Beautiful Matrix
281A Word Capitalization
282A Bit++
318A Even Odds
339A Helpful Maths
339B Xenia and Ringroad
455A Boredom
459B Pashmak and Flowers
474B Worms
479A Expression
486A Calculating Function
489B BerSU Ball
489C Given Length and Sum of Digits...
492B Vanya and Lanterns
500A New Year Transportation
507B Amr and Pins
513A Game
520B Two Buttons
550A Two Substrings
580A Kefa and First Steps
742A Arpa's hard exam and Mehrdad's naive cheat
766B Mahmoud and a Triangle
935A Fafa and his Company
977B Two-gram
977D Divide by three, multiply by two
996A Hit the Lottery
1097A Gennady and a Card Game
1108A Two distinct points
1154A Restoring Three Numbers