Number theory

Overview
Number Theory is the queen of mathematics. It deals with the different properties of numbers such as integers, real numbers, fractions and other pure mathematical concepts. It includes determining the properties of prime numbers, divisibility of numbers and completing large calculations in short amounts of time. For example, an N-Queens solution can be checked for incorrectness by labeling each position (or square) of the chessboard with a number from 1 to n*n starting in the top-left corner and moving from left-to-right and top-to-bottom (or another symmetrical version of this), summing the values of the positions of the queens, and checking that value against $$\frac{n(n+1)}{2}$$. If they do not match, then answer is incorrect. However, if they do match then each queen is on a unique row and column, but the queens may or may not be attacking one another diagonally.

Prime Number Generation
Prime numbers are a prime example of what Number Theory is about, as they have important real-world applications (RSA is built upon the difficulty of factoring the product of two large primes). Therefore, the generation of accurate prime numbers is integral to the success of these systems.

There are a few methods for determining if a number is prime, but first a simple working definition of a prime is essential. A prime is a number that is greater than 1 and cannot be divided by anything other than 1 and itself (i.e.- 7 is prime as it has no divisors other than 1 and 7 [itself], whereas 6 is not prime as it can be divided by 1, 2, 3, and 6 [itself]). Due to this definition, we can exclude at least one group of numbers- by definition, all even numbers are divisible by 2, and are therefore not prime.

Now we can get into verifying whether a number is a prime or not. A prime, by definition, is not divisible by anything in the range $$[2, n)$$, so we could check if a number is divisible by every number in that range, but that would take way more time than is necessary. This is because as we move above the square root of the number, the multiplication pairs begin to repeat, therefore we can go from $$[2, n)$$ to a significantly reduced search space of $$[2, \lceil \sqrt{n} \rceil]$$. Also important to note is that you can specifically ensure multiples of specific numbers are not checked, as 2 and 3 are normally considered as separate cases. This will reduce time and algorithmic complexity due to significantly fewer checks per operation. This is generally referred to as a naïve approach as it is usually the first method thought of and has minimal optimization.

This is a simple implementation in Python: def naive(n): if n%2==0 or n%3==0:       # check if 'n' is a multiple of 2 or 3 (assumes you aren't checking 2 or 3 through this function) return False           # if it is, it's not prime sqrt=int(((n**.5+1)//1)-1) # efficient square root ceiling function for x in range(5, sqrt, 2): # check from 5 (next prime) to sqrt, but only every other number (the odds) if n%x==0:             # if n is divisible by a number less than it (x) return False       # then it is not prime return True                # it has checked every number from [2, sqrt] and isn't divisible by any, so it is prime

This will return if it is a prime number or not every time, accurately, but this function will take forever with larger numbers.

Efficient Prime Generation : Sieve
This is one of the algorithm of beginner level to generate Prime numbers. This is sometime called Sieve of Eratosthenes. Let's dive in. Let's assume we have an array from 1 to 20. We will surely skip 1, as it is debatable. Let's start from 2. It is prime, we know. So delete all number divisible by 2, except 2, from the list - 4,6,8,10,12,14,16,18,20 are gone. We will put 2 in another list, a prime list[maybe ? - or whatever you call] Remaining from the list are - 3,5,7,9,11,13,15,17,19. Pick the the first remaining from the list - 3. Let's remove all divisible by 3 except 3 from the remaining list, now we are left with - 5,7,11,13,17,19. And prime list looks like - 2,3.

After doing the same for 5 - Prime List (2,3,5) - Remaining (7,11,13,17,19)

After doing the same for 7 - Prime List (2,3,5,7) - Remaining (11,13,17,19)

After doing the same for 11 - Prime List (2,3,5,7,11) - Remaining (13,17,19)

After doing the same for 13 - Prime List (2,3,5,7,11,13) - Remaining (17,19)

After doing the same for 17 - Prime List (2,3,5,7,11,13,17) - Remaining (19)

After doing the same for 19 - Prime List (2,3,5,7,11,13,17,19) - Remaining

Now we have all primes between 1 to 20 - 2,3,5,7,11,13,17,19.

There can be multiple implementation of Sieve, let's try this : using namespace std; bool arr[N+1];                                    //As we want to directly use those indices we will have an array of size N+1, simply to use N'th index int main {   memset(arr,true,sizeof(arr)/sizeof(arr[0]));   //We can initialize by any value, we are using true - which indicates index can be prime, if not we will simply make it false for(int i=2;i<=N;i++)                         //As discussed, we will skip 1, and loop through indices {       if(arr[i]==true)                           //If some index is already false, it means it is not prime, so it's multipliers are not prime, and we don't even have to check those, as they are already taken care of, example, we will skip 6, no need to mark 12,18,.. they are already marked not-prime by 2 or 3, the same reason which cancelled 6. {           for(int j=i*2;j<=N;j+=i)               //We will start from that index's double as that unmarked number is prime, but all it's multipliers are not prime arr[j]=false;                     //Mark them as false }   }    return 0; }
 * 1) include
 * 1) define N 100                                     //Define any value you like, put something small, to test