#include <iostream>
#include <cstdio>
#include <forward_list>
#include <unordered_map>
#include <string>
using namespace std;
/* This is all taken from Rosetta Code's deterministic Miller-Rabin test */
// calcul a^n%mod
unsigned long long power(unsigned long a, unsigned long n, unsigned long mod)
{
unsigned long long power = a;
unsigned long long result = 1;
while (n)
{
if (n & 1)
result = (result * power) % mod;
power = (power * power) % mod;
n >>= 1;
}
return result;
}
// n−1 = 2^s * d with d odd by factoring powers of 2 from n−1
bool witness(unsigned long long n, unsigned long long s, unsigned long long d, unsigned long long a)
{
unsigned long long x = power(a, d, n);
unsigned long long y;
while (s) {
y = (x * x) % n;
if (y == 1 && x != 1 && x != n-1)
return false;
x = y;
--s;
}
if (y != 1)
return false;
return true;
}
/*
* if n < 1,373,653, it is enough to test a = 2 and 3;
* if n < 9,080,191, it is enough to test a = 31 and 73;
* if n < 4,759,123,141, it is enough to test a = 2, 7, and 61;
* if n < 1,122,004,669,633, it is enough to test a = 2, 13, 23, and 1662803;
* if n < 2,152,302,898,747, it is enough to test a = 2, 3, 5, 7, and 11;
* if n < 3,474,749,660,383, it is enough to test a = 2, 3, 5, 7, 11, and 13;
* if n < 341,550,071,728,321, it is enough to test a = 2, 3, 5, 7, 11, 13, and 17.
*/
bool is_prime_mr(unsigned int n)
{
if (((!(n & 1)) && n != 2 ) || (n < 2) || (n % 3 == 0 && n != 3))
return false;
if (n <= 3)
return true;
unsigned long d = n / 2;
unsigned long s = 1;
while (!(d & 1)) {
d /= 2;
++s;
}
if (n < 1373653)
return witness(n, s, d, 2) && witness(n, s, d, 3);
if (n < 9080191)
return witness(n, s, d, 31) && witness(n, s, d, 73);
if (n < 4759123141)
return witness(n, s, d, 2) && witness(n, s, d, 7) && witness(n, s, d, 61);
if (n < 1122004669633)
return witness(n, s, d, 2) && witness(n, s, d, 13) && witness(n, s, d, 23) && witness(n, s, d, 1662803);
if (n < 2152302898747)
return witness(n, s, d, 2) && witness(n, s, d, 3) && witness(n, s, d, 5) && witness(n, s, d, 7) && witness(n, s, d, 11);
if (n < 3474749660383)
return witness(n, s, d, 2) && witness(n, s, d, 3) && witness(n, s, d, 5) && witness(n, s, d, 7) && witness(n, s, d, 11) && witness(n, s, d, 13);
return witness(n, s, d, 2) && witness(n, s, d, 3) && witness(n, s, d, 5) && witness(n, s, d, 7) && witness(n, s, d, 11) && witness(n, s, d, 13) && witness(n, s, d, 17);
}/* This was all taken from Rosetta Code's deterministic Miller-Rabin test */
bool is_prime(unsigned int n)
{
if((n > 2) && !(n % 2)) return false;
if((n > 3) && !(n % 3)) return false;
if((n > 5) && !(n % 5)) return false;
if((n > 7) && !(n % 7)) return false;
if((n > 11) && !(n % 11)) return false;
if((n > 13) && !(n % 13)) return false;
if((n > 17) && !(n % 17)) return false;
if((n > 19) && !(n % 19)) return false;
if((n > 23) && !(n % 23)) return false;
if((n > 29) && !(n % 29)) return false;
if((n > 31) && !(n % 31)) return false;
if((n > 37) && !(n % 37)) return false;
if((n > 41) && !(n % 41)) return false;
if((n > 43) && !(n % 43)) return false;
if((n > 47) && !(n % 47)) return false;
if((n > 53) && !(n % 53)) return false;
if((n > 59) && !(n % 59)) return false;
if((n > 61) && !(n % 61)) return false;
if((n > 67) && !(n % 67)) return false;
if((n > 71) && !(n % 71)) return false;
if((n > 73) && !(n % 73)) return false;
if((n > 79) && !(n % 79)) return false;
return is_prime_mr(n);
}
bool is_valid_pair(unsigned int a, unsigned int b)
{
if(a >= b) return false;
if(a+b > 26021) return false;
// Only prime numbers should be past this point, so no need to test a and b for primality
if((a+b)%3 == 0) return false;
if (is_prime(stol(to_string(a)+to_string(b)))==false) return false;
if (is_prime(stol(to_string(b)+to_string(a)))==false) return false;
return true;
}
main() {
double duration;
int nprimes;
forward_list<unsigned int> Primes;
unordered_map<unsigned int,bool> Pairs;
// Find the primes
for(unsigned int i=2;i<26000;i++) if(is_prime(i)) Primes.push_front(i);
Primes.reverse();// Find the prime pairs
for ( auto it = Primes.begin(); it != Primes.end(); ++it ) {
for ( auto jt = next(it,1); jt != Primes.end(); ++jt ) {
if(is_valid_pair(*it, *jt)) Pairs.emplace (stol(to_string(*it)+to_string(*jt)),true);
else Pairs.emplace (stol(to_string(*it)+to_string(*jt)),false);
}
}// Now build the tuples
unsigned int smallest = 26034;
for ( auto it = Primes.begin(); it != Primes.end(); ++it ) {
for ( auto jt = next(it,1); jt != Primes.end(); ++jt ) {
if(Pairs[stol(to_string(*it)+to_string(*jt))]) {
for ( auto kt = next(jt,1); kt != Primes.end(); ++kt ) {
if(Pairs[stol(to_string(*it)+to_string(*kt))] &&
Pairs[stol(to_string(*jt)+to_string(*kt))]) {
for(auto lt = next(kt,1); lt != Primes.end(); ++lt ) {
if(Pairs[stol(to_string(*it)+to_string(*lt))] &&
Pairs[stol(to_string(*jt)+to_string(*lt))] &&
Pairs[stol(to_string(*kt)+to_string(*lt))]) {
for(auto mt = next(lt,1); mt != Primes.end() && *it+*jt+*kt+*lt+*mt < smallest; ++mt ) {
if(Pairs[stol(to_string(*it)+to_string(*mt))] &&
Pairs[stol(to_string(*jt)+to_string(*mt))] &&
Pairs[stol(to_string(*kt)+to_string(*mt))] &&
Pairs[stol(to_string(*lt)+to_string(*mt))]) {
if(*it+*jt+*kt+*lt+*mt < smallest) {
smallest = *it+*jt+*kt+*lt+*mt;
cout << *it << " " << *jt << " " << *kt <<" " << *lt << " " << *mt << " = ";
cout << smallest << endl;
} // smallest thus far
} // 5-plet
} // m-loop
} // 4-plet
} // l-loop
} // 3-plet
} // k-loop
} // 2-plet
} // j-loop
} //i-loop
return 0;
}