Prime number (SIGSEGV) - c++

This is a very famous problem on SPOJ where you need to find prime numbers in a given range so the thing is the range lies from 1 to 1000000000.But every time i allocate an array of 1000000000 size it will give me a sigsegv error or a sigabrt error how do i overcome this problem of assigning very large values to an array
Apart from that i am using the sieve of ertosthenes algorithm to solve the problem.I have given the code below please help me resolve the problem by telling me what i need to change in my code so i don't get a sigsegv and sigabrt error.
#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
int t,j;
long long int x,y;
cin>>t;
int i=0;
while(i<t)
{
cin>>x>>y;
long long int *a=new long long int[y];
for(int k=0;k<=y;k++)
a[k]=1;
a[0]=0;
a[1]=0;
for(int k=2;k<=y;k++)
{
if(a[k]==1)
{
for(j=2;k*j<=y;j++)
a[k*j]=0;
}
}
for(int k=x;k<=y;k++)
{
if(a[k]==1)
cout<<k;
}
delete []a;
i++;
}
return 0;
}

please help me resolve the problem by telling me what i need to change in my code so i don't get a sigsegv and sigabrt error.
Change:
long long int *a=new long long int[y];
to:
std::vector<bool> a=std::vector<bool>(y);
std::vector<bool> will allocate 1 bit for each 0/1 value, instead of the 64 bits that you are probably allocating for each.

It looks like you're using something similar to the Sieve of Eratosthenes. The algorithm looks like:
bool composite[N] := {false, ..., false}
composite[0] := true
composite[1] := true
for (i from 2 to N)
if (not composite[i])
for (j = 2i to N skipping by i)
composite[j] := true
For ranges like [1, 10^9], a nice option to cut memory usage is to use bit masking instead of booleans. This way, you use ~128MB instead of ~1GB of memory for the sieve. Edit: I forgot to mention that std::vector<bool> is actually internally a std::bitset, so you don't actually have to do any explicit bit twiddling.
A better option in terms of memory is to use the fact that a number is composite iff it has a non-trivial factor less than or equal to its square root, and combine that with a sieve. Of course, you have to augment the sieve with a list of primes. It will be empty initially, and you must append a prime each time you find one.
Sieve all of the primes up to 32,000 (A little more than the square root of 1,000,000,000). The result is a sorted sequence of prime numbers.
For each integer k, iterate over the primes less than or equal to the square root of k. If it's divisible by one of them, it's not prime. Otherwise, if the loop terminates, it's prime. When k < 32,000, you can avoid this entirely and just use the flag set in the sieve array.
This gives you O(sqrt(N) log log sqrt(N)) complexity for the sieve, and checking if an integer k is prime takes time O(sqrt(k) / log sqrt(k)) by the Prime Number Theorem.

Related

Wrong result for code doing dynamic programming in C++

I am solving a dp problem .The problem is that I have N dices; each of them has K faces numbered from 1 to K. Now I have arranged the N dices in a line. I can rotate/flip any dice if I want. How many ways I can set the top faces such that the summation of all the top faces equals S?
Now I am given N, K, S; I have to calculate the total number of ways.It is worthy of mention I have to print the result modulo 100000007.I have tried to solve this problem and write a code for this one but my code doesn't work for this case:800 800 10000 why? I can't understand .Can anyone explain the cause for which my code doesn't work. My code is here:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<memory.h>
#define M 100000007
#define ull unsigned long long
using namespace std;
ull n,K,s,dp[1001][1001];
ull fnc(int num,int sum,int k)
{
ull temp;
if(num==0){
if(sum==0) return 1;
else return 0;
}
if(dp[num][k]!=-1)
return dp[num][k];
for(int i=1;i<=K;i++)
{
temp=temp%M+fnc(num-1,sum-i,i)%M;
}
return dp[num][k]=temp%M;
}
int main()
{
int T;
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>n>>K>>s;
memset(dp,-1,sizeof(dp));
printf("Case %d: %lld\n",t,fnc(n,s,0));
}
return 0;
}
You used the wrong subscripts for dp.
Consider how many ways you can get 800 dice, each with numbers from 1 to 800,
to have the sum 10000 if you make the number 1 uppermost on the first die
and you make 4 uppermost on the second die.
Now consider how many ways to have the sum 10000 if you make 2 uppermost on the first die
and 3 uppermost on the second die.
Those two quantities are the same: each is the number of ways to get 798 dice (with numbers 1 to 800) to have the sum 99995. That is the kind of quantity you want to memoize.
But you have not even allocated enough space in dp to store this kind of partial answer.
I also have to wonder why you are using unsigned long long rather than just unsigned long, since your answer is to be given modulo 100000007. You should never have to
work with numbers that are even near the maximum value of a signed long.
According to http://linux.die.net/man/3/memset :
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.
Note it doesn't say "the constant unsigned long long c".
You have the value k and K defined in the same scope, which is infuriating.
You hard coded 1001 and -1 instead of giving them proper soft coded variable names.
Most of your variable names are 1 character long.
You have persistent behavior in a return statement.
You have absolutely nothing checking if the values of k, K, and num are within the proper range of dp, which is partially a consequence of hard coding 1001.
Spacebar is your friend, writingcodelikethisthatwehavetoreadisannoying.

Segmentation Fault C++ (array too large?)

I'm working on the Project Euler Problem 14, where I need to find the longest collatz sequence under 1,000,000. I've come up with an algorithm that works for smaller numbers (say, 100) that stores each collatz number from 1 - 100 into an array and uses that array as a reference to speed up the computations for higher numbers.
My code is as follows:
#include <iostream>
using namespace std;
long even(long n){ //the even-collatz function
n=n/2;
return n;
}
long odd(long n){ //the odd collatz function
n=3*n+1;
return n;
}
int main(){
long x, c=0, y[1000000]; // x= the number we are finding the collatz number of, c a counter that keeps track of how many steps we've taken in the sequence, y is an array to store the collatz numbers.
for (x=1; x<1000000; x++){ //iterates from x=1 to 1 million
long a = x; //sets a number a equal to the number we are currently trying to find the collatz number of
long b = a;
c=0; //intializes counter at 0
while (a!=0){ //loops infinitely; the only way to exit is through a break.
if (a%2==0){ // detects if the number is even
a=even(a); //applies the even-collatz function if so; sets x=x/2
c=c+1;
if (y[a]!=0){ // checks if the collatz number of x is already discovered
y[b]=c+y[a]; //adds the current number of steps to the collatz number of x and
break; //exits the while loop
}
}
else if (a==1){ //checks if the new x is equal to one and
y[b]=c; //if it is, it writes the current value of c to y[b] and
break; // exits the loop
}
else if (a%2==1){ //same as the "even" block, except for odd numbers
a=odd(a);
c=c+1;
if( y[a]!=0){
y[b]=c+y[a];
break;
}
}
//this is the end of the while loop; we've applied the collatz function as many times as we've needed to to x, and incremented the counter each time
}
}
long z;
for (int n=0;n!=100;n++){
if (y[n+1]>y[n]){
z=y[n+1];
}
}
cout << z << "\n";
}
The issue I'm having is that I get a segfault after x=1818 in the for loop. Through debugging, I've found that how quickly the segfault occurs depends on the size of array y, so I'm assuming that the array is just too big. From my (basic) understanding of segfaults, I think I'm just accessing memory that I'm "not allowed". Is there any way for me to circumvent this, or should I just start working towards another solution to this problem? I'm compiling using g++ on Ubuntu studio.
This array is probably too big for your system's default stack size; the simplest fix is to change its definition to:
std::vector<long> y(1000000);
and everything else can stay the same. You could use y.size() instead of the magic number 1000000 later in your loop.
For a starting number under N collatz sequence can go way beyond N. For N == 1000000 consider x == 333335.
I would suggest you to make y a vector<int> and expand it dynamically, or just make it unordered_map<int, int>.
If y was too big for your stack, you would get a stack overflow exception as soon as main tried to run.
Your problem is more likely that a gets bigger than the size of y.
When I ran it through the debugger, a was 1417174 when x was 4255, so you might have a problem with your algorithm.
That said, you should either allocate it yourself, or make it static, as there is no guarantee that whatever compiler Project Euler uses will allow such a large stack size.

C++ Program hangs when calling a function

I have written a code which checks whether a integer is prime or not,whenever i am calling that function the command line just hangs.
I am using MingW in Windows 7
#include<iostream>
#include<math.h>
using namespace std;
bool checkPrime(int n);
int main()
{
int t,tempstart;
cout<<checkPrime(6);
return 0;
}
bool checkPrime(int n)
{
bool check=true;
for (int i = 0; i <(int) sqrt(n) ; i++)
{
if(n%i==0)
{
check=false;
cout<<"asas";
break;
}
}
return check;
}
it should not hang-up at least not for n=6
1.try this
instead of:
if(n%i==0)
write:
if((n%i)==0)
some compilers do a mess with multi operation conditions so bracketing usually helps
2.as mentioned i should go from 2
n%0 is division by zero maybe your code thrown hidden exception and that is what is wrong
3.have you try to debug it ?
get a breakpoint inside for loop and step it and see why it is not stopping when i==2,3
Tips for speeding it up a little (just few thousand times for bigger n)
1.i=2,3,5,7,9,11,13,...
as mentioned in comments do i=2 separately (by (n&1)==0 instead of (n%2)==0)
and the rest:
for (nn=sqrt(n),i=3;i<=nn;i+=2) ...
2.instead of sqrt(n) use number with the half of bits
3.do not compute sqrt inside for (some compilers do not pre-compute)
4.use sieve of Aristoteles
create one or more arrays which will eliminate few divisions from you
do not forget to use array size as common multiply of dividers inside it
this is what can speed up things considerably
because it can eliminate many for cycles with a single array access
but it need initialization of arrays prior to their use
for example array
BYTE sieve[4106301>>1]; //only odd numbers are important so the size is half and each bit hold one sieve value so the size is really 4106301*8 which is divided by:
can hold sieves for dividers:
3,5,7,11,13,17,19,23,137,131,127,113,83,61,107,101,
103,67,37,41,43,53,59,97,89,109,79,73,71,31,29
5.divide by primes
you can remember first M primes in some array (for example first 100 primes)
and divide by them
and the use
for (nn=sqrt(n),i=last prime+2;i<=nn;i++) ...
also you can remember all primes computed on runtime in some list and use them
6.you can combine all above all together
7.there are many other ways to improve performance of is_prime(n) ?
so study if you need more speed
According to the operator precedence in C++
% has more priority than ==
so you should be using
if((n%i)==0)
good luck!

Optimizing my code for finding the factors of a given integer

Here is my code,but i'lld like to optimize it.I don't like the idea of it testing all the numbers before the square root of n,considering the fact that one could be faced with finding the factors of a large number. Your answers would be of great help. Thanks in advance.
unsigned int* factor(unsigned int n)
{
unsigned int tab[40];
int dim=0;
for(int i=2;i<=(int)sqrt(n);++i)
{
while(n%i==0)
{
tab[dim++]=i;
n/=i;
}
}
if(n>1)
tab[dim++]=n;
return tab;
}
Here's a suggestion on how to do this in 'proper' c++ (since you tagged as c++).
PS. Almost forgot to mention: I optimized the call to sqrt away :)
See it live on http://liveworkspace.org/code/6e2fcc2f7956fafbf637b54be2db014a
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
typedef unsigned int uint;
std::vector<uint> factor(uint n)
{
std::vector<uint> tab;
int dim=0;
for(unsigned long i=2;i*i <= n; ++i)
{
while(n%i==0)
{
tab.push_back(i);
n/=i;
}
}
if(n>1)
tab.push_back(n);
return tab;
}
void test(uint x)
{
auto v = factor(x);
std::cout << x << ":\t";
std::copy(v.begin(), v.end(), std::ostream_iterator<uint>(std::cout, ";"));
std::cout << std::endl;
}
int main(int argc, const char *argv[])
{
test(1);
test(2);
test(4);
test(43);
test(47);
test(9997);
}
Output
1:
2: 2;
4: 2;2;
43: 43;
47: 47;
9997: 13;769;
There's a simple change that will cut the run time somewhat: factor out all the 2's, then only check odd numbers.
If you use
... i*i <= n; ...
It may run much faster than i <= sqrt(n)
By the way, you should try to handle factors of negative n or at least be sure you never pass a neg number
I'm afraid you cannot. There is no known method in the planet can factorize large integers in polynomial time. However, there are some methods can help you slightly (not significantly) speed up your program. Search Wikipedia for more references. http://en.wikipedia.org/wiki/Integer_factorization
As seen from your solution , you find basically all prime numbers ( the condition while (n%i == 0)) works like that , especially for the case of large numbers , you could compute prime numbers beforehand, and keep checking only those. The prime number calculation could be done using Sieve of Eratosthenes method or some other efficient method.
unsigned int* factor(unsigned int n)
If unsigned int is the typical 32-bit type, the numbers are too small for any of the more advanced algorithms to pay off. The usual enhancements for the trial division are of course worthwhile.
If you're moving the division by 2 out of the loop, and divide only by odd numbers in the loop, as mentioned by Pete Becker, you're essentially halving the number of divisions needed to factor the input number, and thus speed up the function by a factor of very nearly 2.
If you carry that one step further and also eliminate the multiples of 3 from the divisors in the loop, you reduce the number of divisions and hence increase the speed by a factor close to 3 (on average; most numbers don't have any large prime factors, but are divisible by 2 or by 3, and for those the speedup is much smaller; but those numbers are quick to factor anyway. If you factor a longer range of numbers, the bulk of the time is spent factoring the few numbers with large prime divisors).
// if your compiler doesn't transform that to bit-operations, do it yourself
while(n % 2 == 0) {
tab[dim++] = 2;
n /= 2;
}
while(n % 3 == 0) {
tab[dim++] = 3;
n /= 3;
}
for(int d = 5, s = 2; d*d <= n; d += s, s = 6-s) {
while(n % d == 0) {
tab[dim++] = d;
n /= d;
}
}
If you're calling that function really often, it would be worthwhile to precompute the 6542 primes not exceeding 65535, store them in a static array, and divide only by the primes to eliminate all divisions that are a priori guaranteed to not find a divisor.
If unsigned int happens to be larger than 32 bits, then using one of the more advanced algorithms would be profitable. You should still begin with trial divisions to find the small prime factors (whether small should mean <= 1000, <= 10000, <= 100000 or perhaps <= 1000000 would need to be tested, my gut feeling says one of the smaller values would be better on average). If after the trial division phase the factorisation is not yet complete, check whether the remaining factor is prime using e.g. a deterministic (for the range in question) variant of the Miller-Rabin test. If it's not, search a factor using your favourite advanced algorithm. For 64 bit numbers, I'd recommend Pollard's rho algorithm or an elliptic curve factorisation. Pollard's rho algorithm is easier to implement and for numbers of that magnitude finds factors in comparable time, so that's my first recommendation.
Int is way to small to encounter any performance problems. I just tried to measure the time of your algorithm with boost but couldn't get any useful output (too fast). So you shouldn't worry about integers at all.
If you use i*i I was able to calculate 1.000.000 9-digit integers in 15.097 seconds. It's good to optimize an algorithm but instead of "wasting" time (depends on your situation) it's important to consider if a small improvement really is worth the effort. Sometimes you have to ask yourself if you rally need to be able to calculate 1.000.000 ints in 10 seconds or if 15 is fine as well.

Project Euler Problem 12 - C++

I'm working on problem 12 regarding the first triangle number with 500 divisors. I tried to brute force the solution. I get 300 divisors in about 35 seconds and can't get 400 within 10 minutes. I'm going to alter my solution to use the prime factor method but I've seen now that people are still getting this solution with brute force in under a minute.
Can you please critique my code and tell me if I'm missing something that is making this horribly inefficient?
unsigned long long TriangleNumberDivisors(int divisorTarget)
{
unsigned long long triangleNum=1;
unsigned long long currentNum=2;
int numOfDivisors=0;
numOfDivisors=NumOfDivisors(triangleNum);
while(numOfDivisors<divisorTarget)
{
triangleNum+=currentNum;
currentNum++;
numOfDivisors=NumOfDivisors(triangleNum);
}
return triangleNum;
}
int NumOfDivisors(unsigned long long dividend)
{
int numDivisors=0;
set<unsigned long long> divisors;
set<unsigned long long>::iterator it;
for(unsigned long long index=1; index<=dividend/2; index++)
{
if(dividend%index==0)
{
divisors.insert(index);
numDivisors++;
it=divisors.find(dividend/index);
if(it==divisors.end())
{
divisors.insert(dividend/index);
numDivisors++;
}
/*for some reason not checking for dups above and
just checking for how many items are in the set at the end is slower
for(it=divisors.begin();it!=divisors.end();it++)
{
numDivisors++;
}
*/
}
}
return numDivisors;
}
int main()
{
cout<<TriangleNumberDivisors(500)<<endl;
return 0;
}
Update: Got it now, thanks. Changed to just check up to square root of the number, and did an additional check to see if it was a perfect square. This allowed me to remove the set entirely as well. 500 divisors ran in 12 seconds.
You currently check for divisors up to dividend/2. You can reduce this to sqrt(dividend), which is asymptotically faster. A special case may be needed if dividend is square.
My C++ code for problem 12 (which does essentially the same as yours, but uses this lower limit, and also just counts divisors rather than storing them in the set) takes about 1 second
for(unsigned long long index=1; index<=dividend/2; index++)
I see you've tried to optimize this by restricting your loop to dividend/2, instead of iterating all the way to dividend. Limiting yourself to sqrt(dividend) would be better (in the sense that you're checking fewer divisors).
Plus, if you limit yourself by the square root of dividend, you don't have to check for duplicate divisors. That will only happen for square numbers, so just check if index==dividend/index, to avoid a duplicate insert.
I am not sure why you need the divisors, a set type variable, in the NumOfDivisors method. Why counting numDivisors (with index upto sqrt( dividend )) is not sufficient? (set is implemented as a balanced binary search tree, it is slowing down the method. ). Moreover, it seems that you are invoking divisors.insert( .. ) twice.
Seems like you could gain some performance if you cached the number of divisors for a particular number as you went along.