Im currently trying to solve the prime-k factor problem, where I have to find the sum of all primes factorial 1-5 ! and then mod(%) to itself. An example would be the prime 7.
(7-1)!+(7-2)!....(7-5)!=...%7.
The answer to this would be 4. I have to find this answer to the sum of all primes to 10^8. Therefore I have written the following code(which I know I not optimized)!.
#include<iostream>
#include<vector>
using namespace std;
bool prime(unsigned long long int n){
if (n==2 || n==3){
return true;
}
if (n % 2 == 0 || n % 3 == 0) return false;
for (unsigned long long int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
vector<unsigned long long int> Prime_lst(unsigned long long int n){
vector<unsigned long long int> v {};
for(unsigned long long int i = 5; i<n+1; i++){
if(prime(i)==1){
v.insert(v.end(), i);
}
}
return v;
}
unsigned long long int factorial(unsigned long long int n)
{
unsigned long long int res = 1;
for (unsigned long long int i = 2; i <= n; i++)
res *= i;
return res;
}
unsigned long long int prime_p(unsigned long long int n){
unsigned long long int c = 0;
for(int i = 1; i<6; i++){
c += factorial(n-i);
}
return c%n;
}
unsigned long long int sum_prime_p(unsigned long long int n){
unsigned long long int k = 0;
vector<unsigned long long int> prime_lst = Prime_lst(n);
for(unsigned long long int i = 0; i<prime_lst.size(); i++){
cout << k << " ";
k += prime_p(prime_lst.at(i));
}
return k;
}
int main(){
//vector<unsigned long long int> v = Prime_lst(100);
//for(auto i=v.begin(); i<v.end(); i++)
//{
// cout<<" "<<*i << " ";
//}
cout << sum_prime_p(100);
return 0;
}
I have to get 480, but I always get 305 due to ints being 32 bits therefore I have used unsigned long long int. But I still can't get the right answer. Hope someone can help:)!
First of all, here is a link to the original problem: https://projecteuler.net/problem=381
Solution with N=100:
Sum( S(p) ) = 480
Solution with N=100'000'000:
Sum( S(p) ) = 139602943319822
You do not need to sum over 5 factorials; you can reduce to 1. For small n it is reasonable to do these modulo p (as already noted). However, for large n you need a faster way. (Sorry to have to turn the maths into an image).
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
using INT = unsigned long long;
//======================================================================
vector<int> sieve( int nmax )
{
vector<bool> is_prime( 1 + nmax, true );
is_prime[0] = is_prime[1] = false;
for ( int i = 4; i <= nmax; i += 2 ) is_prime[i] = false;
int imx = sqrt( nmax + 0.5 );
for ( int i = 3; i <= imx; i += 2 )
{
if ( is_prime[i] )
{
for ( int j = i * i; j <= nmax; j += 2 * i ) is_prime[j] = false;
}
}
vector<int> primes;
for ( int i = 2; i <= nmax; i++ ) if ( is_prime[i] ) primes.push_back( i );
return primes;
}
//======================================================================
INT ipow( INT X, INT p, INT M )
{
INT result = 1;
while ( p )
{
if ( p % 2 ) result = ( result * X ) % M;
X = ( X * X ) % M;
p /= 2;
}
return result;
}
//======================================================================
int main()
{
// const int N = 100;
const int N = 100'000'000;
auto primes = sieve( N );
INT SumS = 0;
for ( auto p : primes )
{
if ( p < 5 ) continue;
INT S = ( ipow( 24, p-2, p ) * ( 2 * p - 9 ) ) % p;
SumS += S;
}
cout << "Sum( S(p) ) = " << SumS << '\n';
}
//======================================================================