Sieve of Atkin malfunctioning for very high limits - c++

I am attempting to solve Project Euler problem 10 where the user is asked to calculate the sum of all the primes less than two million. I've written the following by studying the pseudocode on Wikipedia but the answer it generates seems to be incorrect, at least according to the website whenever I try to enter it:
int main()
{
int limit = 2000000;
int answer = 5;
std::vector<bool> isPrime;
for( int i = 0; i < limit; ++i ){
isPrime.push_back( false );
}
int n = 0;
for( int x = 1; x <= ceil( sqrt( limit ) ); ++x ){
for( int y = 1; y <= ceil( sqrt( limit ) ); ++y ){
n = 4*x*x + y*y;
if( (n <= limit) && ( n%12 == 1 || n%12 == 5 ) ){
isPrime.at(n) = ! isPrime.at(n);
}
n = 3*x*x + y*y;
if( (n <= limit) && ( n%12 == 7 ) ){
isPrime.at(n) = ! isPrime.at(n);
}
n = 3*x*x - y*y;
if( (x > y) && (n <= limit) && (n%12 == 11) ){
isPrime.at(n) = ! isPrime.at(n);
}
}
}
for( n = 6; n <= ceil( sqrt( limit ) ); n += 2 ){
if( isPrime.at(n) ){
for( int m = n*n; m < limit; m += n*n ){
isPrime.at(m) = false;
}
}
}
for( int i = 5; i < limit; i += 2 ){
if( isPrime.at(i) ){
answer += i;
}
}
std::cout << "The sum of the primes below " << limit << " is " << answer << std::endl;
return 0;
}
The following output is generated:
The sum of all the primes below 2000000 is 1179908154
I've tested it with smaller limits that I'm able to verify by hand and the code is indeed functioning correctly for those numbers. I've found other peoples implementation which indicate that the answer should be 142913828922, but I can't figure out where their code differs from mine.
Can anyone see what it is I'm doing wrong here?

You only have a signed 32-bit integer for the answer. The actual answer is much higher than can fit in 32 bits, so you have to go over to using 64 bit integers. Try using unsigned long long instead.

You can create your own class to store big numbers.Or u can use an array of integer to store your answer and storing each digit at each index. (Even if unsigned long long not working) :)

Related

Finding sum of all binary expansions of numbers from 1 to n

Recently, I came across a question posted as a challenge at a competitive site. There it was asked to find the sum of all the decimal interpretation of binary representations of numbers from 1 to n. Suppose when n = 4, so, sum will be 1 + 10 + 11 + 100 = 122. Since this number could be very large so answer should be modulo 1000000007.
I came across the following solutions but was not able to optimize it.
#include<iostream>
#include<queue>
using namespace std;
int Mod(string s, int a)
{
int res = 0, i, l = s.size();
for( i = 0 ; i < l ; i++ )
{
res = ( res * 10 + s[i] - '0' ) % a;
}
return res;
}
int main()
{
int t;
cin >> t;
while(t--)
{
long long n;
cin >> n;
int Sum = 0, mod = 1000000007;
queue<string> q;
q.push("1");
while( n > 0 )
{
n--;
string s1 = q.front();
q.pop();
Sum = ( Sum + Mod(s1, mod) ) % mod;
string s2 = s1;
q.push(s1.append("0"));
q.push(s2.append("1"));
}
cout << Sum << endl;
}
return 0;
}
Constraints:
1 <= t <= 10^5, 1 <= n <= 10^18, Allowed Time = 1 sec. Any optimization help would be admirable. Thanks in advance.
After doing some calculative math finally I have come up with the solution. Thanks, to #largest_prime_is_463035818 for providing such hints. Here is my code:
#include<iostream>
#include<cmath>
#define mod 1000000007
using namespace std;
long long power(long long x, long long y)
{
long long res = 1LL;
while(y)
{
if( y & 1LL )
{
res = ( res * x ) % mod;
}
y >>= 1LL;
x = ( x * x ) % mod;
}
return res;
}
int main()
{
long long t;
cin >> t;
while(t--)
{
long long n, i, l, m, s = 0;
cin >> n;
if( n && (!( n & ( n - 1LL ) )) )
{
l = ceil(log2(n)) + 1LL;
}
else
{
l = ceil(log2(n));
}
for( i = 0LL ; i < l ; i++ )
{
if( n & ( 1LL << i ) )
{
m = ( ( ( ( n / ( 1LL << ( i + 1LL ) ) ) * ( 1LL << i ) ) + 1LL ) + ( ( n % ( 1LL << ( i + 1LL ) ) ) % ( 1LL << i ) ) );
}
else
{
m = ( ( n / ( 1LL << ( i + 1LL ) ) ) * ( 1LL << i ) );
}
s = ( s + ( ( ( m % mod ) * power(10, i) ) % mod ) ) % mod;
}
cout << s << endl;
}
return 0;
}

How to make sure atleast m out of n bits are on?

I'm given n sets and need to make sure that atleast m sets are selected. I'm planning to deal with bits.
My approach is:
for i in [0,(2^n)-1]
convert i to binary
if number of 1s are greater than or equal to m
{ Some calculations requiring which bits are on }
Now, is there any other way I can make sure that number of on bits are atleast m ? In my above approach, I'll be wasting time in converting numbers to binary and then checking if no. of on bits are >=m. Is there a way to cut short the loop ? (I'm dealing in C++)
I guess you need to generate bitmasks to select a subset of atleast "m" elements from a set of "n" elements.
This can be easily done if we have an algorithm to generate all the bitmasks having exactly "m" bits set.
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// Given "n" and "r", generate all the possible nCr subsets of an array of size "n"
typedef unsigned long long ULL;
// Generate the lowest number bigger than "num" having exactly "r" set bits
// Algorithm (From Cracking The Coding Interview, 5th Edition) -:
// 1. Find the position of the rightmost "non-trailing" zero (such that there is atleast one '1' on its right).
// Let this position be 'p'
// If there does not exist such a zero, the input is already the largest number possible.
// 2. Flip the bit at 'p' to 1 from 0.
// 3. Count the number of zeroes and ones to the right of 'p'.
// Let that number be c0 and c1 respectively.
// 4. Set all the bits to the right of 'p' to 0.
// 5. Set the first (c1-1) bits (starting from the right) to 1.
ULL NextBigger( ULL num )
{
ULL numBak = num;
// Compute c0 and c1
// c0 = Number of zeroes to the right of the rightmost non-trailing zero
size_t c0 = 0;
// c1 = Number of ones to the right of the rightmost non-trailing zero
size_t c1 = 0;
while ( numBak && ( ( numBak & 1 ) == 0 ) )
{
c0++;
numBak >>= 1;
}
while ( ( numBak & 1 ) == 1 )
{
c1++;
numBak >>= 1;
}
// If the input is either 0,
// or of the form "1111..00000",
// then there is no bigger number possible
// Note that for this to work, num should be unsigned
if ( c0 + c1 == 0 || c0 + c1 == ( sizeof( num ) * 8 ) )
{
return 0;
}
// Position of the rightmost non-trailing zero ( starting from the right )
const size_t p = c0 + c1;
// Flip the rightmost non-trailing zero
num |= 1 << p;
// Clear all bits to the right of p
num &= ~( ( 1 << p ) - 1 );
// Insert (c1-1) ones on the right of p
num |= ( 1 << ( c1 - 1 ) ) - 1;
return num;
}
vector<ULL> GenerateSubsets( const size_t& n, const size_t& r )
{
assert( n > 0 );
assert( r > 0 );
assert( n >= r );
vector<ULL> subsets;
// The smallest number having exactly "r" bits set
ULL lowest = ( 1ULL << r ) - 1;
// The biggest number having exactly "r" bits set
ULL highest = lowest << ( n - r );
// The set bits in the binary of "bitMask" denote the positions of the set included in the subset
// This loop should run exactly nCr times
for ( ULL bitMask = lowest; bitMask <= highest; bitMask = NextBigger( bitMask ) )
{
subsets.push_back( bitMask );
}
return subsets;
}
// Extracts the subset indices from the bitmask
vector<size_t> DecodeMask( ULL bitMask )
{
vector<size_t> positions;
size_t i = 0;
while ( bitMask )
{
if ( bitMask & 1 )
{
positions.push_back( i );
}
bitMask >>= 1;
i++;
}
return positions;
}
int main()
{
size_t n = 5;
size_t r = 2;
cout << "Generating subsets of size " << r << "\n";
auto vec = GenerateSubsets( n, r );
cout << "Number of subsets = " << vec.size() << "\n";
// Print the subset indices
for ( size_t i = 0; i < vec.size(); i++ )
{
auto decode = DecodeMask( vec[i] );
for ( size_t j = 0; j < decode.size(); j++ )
{
cout << decode[j] << " ";
}
cout << "\n";
}
}
Now we can easily modify this to generate all the bitmasks having at least "m" bits set by applying the above algo while incrementing "m" upto "n".
// Rest of the code same as above
int main()
{
size_t n = 5;
size_t m = 2;
for ( size_t r = m; r <= n; r++ )
{
cout << "Generating subsets of size " << r << "\n";
auto vec = GenerateSubsets( n, r );
cout << "Number of subsets = " << vec.size() << "\n";
// Print the subset indices
for ( size_t i = 0; i < vec.size(); i++ )
{
auto decode = DecodeMask( vec[i] );
for ( size_t j = 0; j < decode.size(); j++ )
{
cout << decode[j] << " ";
}
cout << "\n";
}
cout << "\n";
}
}

Adding integer with index -2

I went through a interview where I was asked to add 2 integers with -2 index i.e. (-2) power i for the ith bit . I gave the following answer but was told that this answer is not efficient and wrong.I don't agree with the in-efficient comment but may agree with the incorrectness.
The way I added was taking a carry of -1 if the sum of 2 bits is more that equal to 2 because the adjacent bit has the opposite sign. And if adding 2 bits is -1 i make it one and take a carry of 1 to the adjacent bit.
Do any one see any issues with the code?
struct Results solution ( int A[], int M, int B[], int N ) {
struct Results result;
int min =M;
int max = M;
int i=0;
int sum;
int carry = 0;
if(N<M)min = N;
if(N>M)max = N;
result.C = (int*) malloc(sizeof(int) * max);
for(i=0;i<min;i++){
sum = A[i] + B[i] + carry;
if(sum >= 2 ){
if(carry == 0 )
carry = -1;
else
carry = -carry;
sum = sum-2;
}
else if(sum == -1){
sum = 1;
carry = 1;
}
else{
carry=0;
}
result.C[i] = sum;
}
if( M > N){
result.L = M;
for(i=N;i<M;i++){
sum = A[i]+carry;
if(sum >= 2 ){
if(carry == 0 ) carry = -1;
else carry = 1;
sum = sum-2;
}
else if(sum == -1){
sum = 1;
carry = - carry;
}
else{carry=0;}
result.C[i] = sum;
}
}
if( N > M){
result.L = N;
for(i=M;i<N;i++){
sum = B[i]+carry;
if(sum >= 2 ){
if(carry == 0 ) carry = -1;
else carry = -carry;
sum = sum-2;
}
else if(sum == -1){
sum = 1;
carry = 1;
}
else{carry=0;}
result.C[i] = sum;
}
}
return result;
}
int main(int argc, char* argv[])
{
int A[] = {0,1,1,0,0,1,0,1,1,1,0,1,0,1,1};
int B[] = {0,0,1,0,0,1,1,1,1,1,0,1};
solution (A,15,B ,12 );
}
Problem 1
You say you use a carry of -1 if the sum of 2 bits is more that equal to 2 but in one of your cases you have the code:
if(sum >= 2 ){
if(carry == 0 ) carry = -1;
else carry = 1;
sum = sum-2;
}
This will set the carry to 1, not -1.
You could also argue that this code could be written more efficiently as:
if(sum >= 2 ){
carry = -1;
sum = sum-2;
}
Problem 2
What happens if we add {1} and {1}?
You will return a length of 1 and a result of {0}, but the answer should be {0,1,1}. (1+1=-2+4)
In other words, you may need to return more bits than the maximum of the inputs.
O(1) solution: Table lookup.
If you know the number of bits per input, a 2D lookup table does it real fast. If not, you can still do a bunch of bits at a time with it.

How to implement division by addition?

An interview question.
How to implement division by addition? suppose they are all int.
My idea
Add divisor to itself until it is larger than dividend.
Each iteration, keep the sum result before addition.
The quotient is the sum result before the last addition. the remainder can be counted by adding 1 until the quotient * divisor + reminder == dividend.
It is O(e^n), any better ideas? bit operation?
dividing m by n:
int r = m;
int q = 0;
while( r >= n )
{
int k = 1;
int x = n;
int t;
while( ( t = x+x ) < r )
{
x = t;
k += k;
}
q += k;
r -= x;
}
The result is q - quotient, r - remainder.
The idea is that x+x is the same as x*2.
UPD:
Some may complain that r -= x is not addition.
Well we may update the algorithm to not use subtraction:
int p = 0;
int q = 0;
while( p+n <= m )
{
int k = 1;
int x = n;
int t;
while( p + ( t = x+x ) < m )
{
x = t;
k += k;
}
q += k;
p += x;
}
The result is q - quotient.
If we need the remainder then we proceed as follows (p - output from the above):
int r = 0;
while( p < m )
{
int x = 1;
int t;
while( p + ( t = x+x ) < m )
{
x = t;
}
r += x;
p += x;
}
The result is r - remainder.
The algorithm has obviously polynomial (not exponential) running-time.
In digital arithmetic we can name restoring and non-restoring methods as simple division algorithms which are based on addition/subtraction. Number of iterations in these methods are of O(n) (where n is the number of bits). There are methods like Newton-Raphson or reciprocal calculation which are based on multiplication and number of iterations in them are of O(log n). Take a look at http://en.wikipedia.org/wiki/Division_%28digital%29
You would break the division into its logarithmic components and then compute those.
For int numbers you could use this logic:
16 divided by 5 = 3 (i)
i=1 -> 5+0 = 5 < 16
i=2 -> 5+5 = 10 < 16
i=3 -> 5+5+5 = 15 < 16
i=4 -> 5+5+5+5 = 20 > 16
So 3 will be your answer.

C++: compute a number's complement and its number of possible mismatches

I got a bit stuck with my algorithm and I need some help to solve my problem. I think an example would explain better my problem.
Assuming:
d = 4 (maximum number of allowed bits in a number, 2^4-1=15).
m_max = 1 (maximum number of allowed bits mismatches).
kappa = (maximum number of elements to find for a given d and m, where m in m_max)
The main idea is for a given number, x, to compute its complement number (in binary base) and all the possible combinations for up to m_max mismatches from x complement's number.
Now the program start to scan from i = 0 till 15.
for i = 0 and m = 0, kappa = \binom{d}{0} = 1 (this called a perfect match)
possible combinations in bits, is only 1111 (for 0: 0000).
for i = 0 and m = 1, kappa = \binom{d}{1} = 4 (one mismatch)
possible combinations in bits are: 1000, 0100, 0010 and 0001
My problem was to generalize it to general d and m. I wrote the following code:
#include <stdlib.h>
#include <iomanip>
#include <boost/math/special_functions/binomial.hpp>
#include <iostream>
#include <stdint.h>
#include <vector>
namespace vec {
typedef std::vector<unsigned int> uint_1d_vec_t;
}
int main( int argc, char* argv[] ) {
int counter, d, m;
unsigned num_combination, bits_mask, bit_mask, max_num_mismatch;
uint_1d_vec_t kappa;
d = 4;
m = 2;
bits_mask = 2^num_bits - 1;
for ( unsigned i = 0 ; i < num_elemets ; i++ ) {
counter = 0;
for ( unsigned m = 0 ; m < max_num_mismatch ; m++ ) {
// maximum number of allowed combinations
num_combination = boost::math::binomial_coefficient<double>( static_cast<unsigned>( d ), static_cast<unsigned>(m) );
kappa.push_back( num_combination );
for ( unsigned j = 0 ; j < kappa.at(m) ; j++ ) {
if ( m == 0 )
v[i][counter++] = i^bits_mask; // M_0
else {
bit_mask = 1 << ( num_bits - j );
v[i][counter++] = v[i][0] ^ bits_mask
}
}
}
}
return 0;
}
I got stuck in the line v[i][counter++] = v[i][0] ^ bits_mask since I was unable to generalize my algorithm to m_max>1, since I needed for m_max mismatches m_max loops and in my original problem, m is unknown until runtime.
i wrote a code that do what i want, but since i am newbie, it is a bit ugly.
i fixed m and d although this code would work fine for genral m and d.
the main idea is simple, assuming we would like to compute the complement of 0 up to two failure (d= 4,m=2), we will see that max number of possibilities is given by \sum_{i = 0)^2\binom{4}{i} = 11.
The complement to 0 (at 4 bits) is 15
With 1 bit possible mismatch (from 15): 7 11 13 14
with 2 bits possible mismatches (from 15): 3 5 6 9 10 12
i wanted that the output of this program will be a vector with the numbers 15 7 11 13 14 3 5 6 9 10 12 inside it.
i hope that this time i am more clear with presenting my question (although i also supplied the solution). I would appreachiate if someone could point out, in my code, ways to improve it and make it faster.
regards
#include <boost/math/special_functions/binomial.hpp>
#include <iostream>
#include <vector>
#define USE_VECTOR
namespace vec {
#if defined(USE_VECTOR) || !defined(USE_DEQUE)
typedef std::vector<unsigned int> uint_1d_vec_t;
typedef std::vector<uint_1d_vec_t> uint_2d_vec_t;
#else
typedef std::deque<unsigned int> uint_1d_vec_t;
typedef std::deque<uint_1d_vec_t> uint_2d_vec_t;
#endif
}
using namespace std;
void get_pointers_vec( vec::uint_2d_vec_t &v , unsigned num_elemets , unsigned max_num_unmatch , unsigned num_bits );
double get_kappa( int m , int d );
int main( ) {
unsigned int num_elements , m , num_bits;
num_elements = 16;
num_bits = 4; // 2^4 = 16
m = 2;
double kappa = 0;
for ( unsigned int i = 0 ; i <= m ; i++ )
kappa += get_kappa( num_bits , i );
vec::uint_2d_vec_t Pointer( num_elements , vec::uint_1d_vec_t (kappa ,0 ) );
get_pointers_vec( Pointer , num_elements , m , num_bits );
for ( unsigned int i = 0 ; i < num_elements ; i++ ) {
std::cout << setw(2) << i << ":";
for ( unsigned int j = 0 ; j < kappa ; j++ )
std::cout << setw(3) << Pointer[i][j];
std::cout << std::endl;
}
return EXIT_SUCCESS;
}
double get_kappa( int n , int k ) {
double kappa = boost::math::binomial_coefficient<double>( static_cast<unsigned>( n ), static_cast<unsigned>(k) );
return kappa;
}
void get_pointers_vec( vec::uint_2d_vec_t &v , unsigned num_elemets , unsigned max_num_unmatch , unsigned num_bits ) {
int counter;
unsigned num_combination, ref_index, bits_mask, bit_mask;
vec::uint_1d_vec_t kappa;
bits_mask = pow( 2 , num_bits ) - 1;
for ( unsigned i = 0 ; i < num_elemets ; i++ ) {
counter = 0;
kappa.clear();
ref_index = 0;
for ( unsigned m = 0 ; m <= max_num_unmatch ; m++ ) {
num_combination = get_kappa( num_bits , m ); // maximum number of allowed combinations
kappa.push_back( num_combination );
if ( m == 0 ) {
v[i][counter++] = i^bits_mask; // M_0
}
else if ( num_bits == kappa.at(m) ) {
for ( unsigned k = m ; k <= num_bits ; k++ ) {
bit_mask = 1 << ( num_bits - k );
v[i][counter++] = v[i][ref_index] ^ bit_mask;
}
}
else {
// Find first element's index
ref_index += kappa.at( m - 2 );
for( unsigned j = 0 ; j < ( kappa.at(m - 1) - 1 ) ; j++ ) {
for ( unsigned k = m + j ; k <= num_bits ; k++ ) {
bit_mask = 1 << ( num_bits - k );
v[i][counter++] = v[i][ref_index] ^ bit_mask;
}
ref_index++;
}
}
}
}
}