Can't seem to find the error - memory access violation - c++

I'm trying to solve a problem on france IOI about a card game (named "Reussite" on level 4) that requires outputting every odd number, however I keep getting (0xC0000005) code if my input is bigger than about 48000 and I can't seem to find the error. Help!
here's my code:
#include<bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
int n;cin>>n;vector<int> arr(n+1);
for (int i = 2; i < n+1; ++i) {
int m = i;
//error is in this while loop
while (i*m<=n){arr[i*m]=1;m++;}
}
for (int i = 0; i < n+1; ++i) {
if (arr[i]==0) printf("%d \n",i);
}
}

When the value n is at least 46341, its square no longer fits into a 32-bit signed integer, so the expression i*m results in an integer overflow.
You might want to cast the values to long long, like while ((long long)i*m<=n) or while (i*1LL*m<=n), or change your code otherwise.

Related

Doing away with Runtime Error(SIGSEGV)

I don't think in my code I tried accessing null pointers, or initialising large arrays, someone help please, I dunno where the Runtime Error(SIGSEGV) is coming from. Question to problem can be found at https://www.codechef.com
/MARCH18B/problems/MINEAT
edit:
I think i found out, NathanOliver was right, v1, because of my code, happens to be sometimes empty. Some answers were actually found out of my loop (above n). Thanks alot. I fixed that and I finally got AC, but just 30 points, my code took an additional 0.01 seconds to run. Can anyone help me optimize it, based on Problem statement, Please.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t; cin>>t; while(t--)
{
int n = 0, h = 0; cin>>n>>h;
vector<int> v; vector<int> v1;
for(int i = 0; i != n; i++){int a; cin>>a; v.push_back(a);}
for(int j = 1; j <= h; j++)
{
int hold = 0;
for(auto k : v)
{
if (j >= k){hold +=1;}
else if (j < k){if(k % j == 0){hold += (k/j);} else{hold += ((k/j)+1);}}
}
if (hold <= h){v1.push_back(j);}
}
cout<<*min_element(v1.begin(),v1.end())<<endl;
}
}
Did you check the min_element function's return value? According to the user input, min_element function returns an iterator to 'last element' which is basically a nullptr. Since you're dereferencing it directly, you get the error.

Trouble sieving primes from a large range

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int main() {
int t,m,n;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&m,&n);
int rootn=sqrt(double(n));
bool p[10000]; //finding prime numbers from 1 to square_root(n)
for(int j=0;j<=rootn;j++)
p[j]=true;
p[0]=false;
p[1]=false;
int i=rootn;
while(i--)
{
if(p[i]==true)
{
int c=i;
do
{
c=c+i;
p[c]=false;
}while(c+p[i]<=rootn);
}
};
i=0;
bool rangep[10000]; //used for finding prime numbers between m and n by eliminating multiple of primes in between 1 and squareroot(n)
for(int j=0;j<=n-m+1;j++)
rangep[j]=true;
i=rootn;
do
{
if(p[i]==true)
{
for(int j=m;j<=n;j++)
{
if(j%i==0&&j!=i)
rangep[j-m]=false;
}
}
}while(i--);
i=n-m;
do
{
if(rangep[i]==true)
printf("%d\n",i+m);
}while(i--);
printf("\n");
}
return 0;
system("PAUSE");
}
Hello I'm trying to use the sieve of Eratosthenes to find prime numbers in a range between m to n where m>=1 and n<=100000000. When I give input of 1 to 10000, the result is correct. But for a wider range, the stack is overflowed even if I increase the array sizes.
               
A simple and more readable implementation
void Sieve(int n) {
int sqrtn = (int)sqrt((double)n);
std::vector<bool> sieve(n + 1, false);
for (int m = 2; m <= sqrtn; ++m) {
if (!sieve[m]) {
cout << m << " ";
for (int k = m * m; k <= n; k += m)
sieve[k] = true;
}
}
for (int m = sqrtn; m <= n; ++m)
if (!sieve[m])
cout << m << " ";
}
Reason of getting error
You are declaring an enormous array as a local variable. That's why when the stack frame of main is pushed it needs so much memory that stack overflow exception is generated. Visual studio is tricky enough to analyze the code for projected run-time stack usage and generate exception when needed.
Use this compact implementation. Moreover you can have bs declared in the function if you want. Don't make implementations complex.
Implementation
typedef long long ll;
typedef vector<int> vi;
vi primes;
bitset<100000000> bs;
void sieve(ll upperbound) {
_sieve_size = upperbound + 1;
bs.set();
bs[0] = bs[1] = 0;
for (ll i = 2; i <= _sieve_size; i++)
if (bs[i]) { //if not marked
for (ll j = i * i; j <= _sieve_size; j += i) //check all the multiples
bs[j] = 0; // they are surely not prime :-)
primes.push_back((int)i); // this is prime
} }
call from main() sieve(10000);. You have primes list in vector primes.
Note: As mentioned in comment--stackoverflow is quite unexpected error here. You are implementing sieve but it will be more efficient if you use bistet instead of bool.
Few things like if n=10^8 then sqrt(n)=10^4. And your bool array is p[10000]. So there is a chance of accessing array out of bound.
I agree with the other answers,
saying that you should basically just start over. 
Do you even care why your code doesn’t work?  (You didn’t actually ask.)
I’m not sure that the problem in your code
has been identified accurately yet. 
First of all, I’ll add this comment to help set the context:
// For any int aardvark;
// p[aardvark] = false means that aardvark is composite (i.e., not prime).
// p[aardvark] = true means that aardvark might be prime, or maybe we just don’t know yet.
Now let me draw your attention to this code:
int i=rootn;
while(i--)
{
if(p[i]==true)
{
int c=i;
do
{
c=c+i;
p[c]=false;
}while(c+p[i]<=rootn);
}
};
You say that n≤100000000 (although your code doesn’t check that), so,
presumably, rootn≤10000, which is the dimensionality (size) of p[]. 
The above code is saying that, for every integer i
(no matter whether it’s prime or composite),
2×i, 3×i, 4×i, etc., are, by definition, composite. 
So, for c equal to 2×i, 3×i, 4×i, …,
we set p[c]=false because we know that c is composite.
But look closely at the code. 
It sets c=c+i and says p[c]=false
before checking whether c is still in range
to be a valid index into p[]. 
Now, if n≤25000000, then rootn≤5000. 
If i≤ rootn, then i≤5000, and, as long as c≤5000, then c+i≤10000. 
But, if n>25000000, then rootn>5000,†
and the sequence i=rootn;, c=i;, c=c+i;
can set c to a value greater than 10000. 
And then you use that value to index into p[]. 
That’s probably where the stack overflow occurs.
Oh, BTW; you don’t need to say if(p[i]==true); if(p[i]) is good enough.
To add insult to injury, there’s a second error in the same block:
while(c+p[i]<=rootn). 
c and i are ints,
and p is an array of bools, so p[i] is a bool —
and yet you are adding c + p[i]. 
We know from the if that p[i] is true,
which is numerically equal to 1 —
so your loop termination condition is while (c+1<=rootn);
i.e., while c≤rootn-1. 
I think you meant to say while(c+i<=rootn).
Oh, also, why do you have executable code
immediately after an unconditional return statement? 
The system("PAUSE"); statement cannot possibly be reached.
(I’m not saying that those are the only errors;
they are just what jumped out at me.)
______________
† OK, splitting hairs, n has to be ≥ 25010001
(i.e., 50012) before rootn>5000.

3n+1 on UVa (C++)

The link to the 3n+1 problem on UVa is:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36
My code is :
#include<iostream>
using namespace std;
long long l(long long n)
{
if(n==1)
{
return 1;
}
if(n%2)
{
return 1+l(3*n+1);
}
else
{
return 1+l(n/2);
}
}
int main()
{
long long i,j,k,max=0,f,g;
while(!cin.eof())
{
cin>>i>>j;
f=i;
g=j;
if(i>j)
{
long long temp;
temp=i;
i=j;
j=temp;
}
max=0;
for(long long a=i;a<=j;a++)
{
k=l(a);
if(k>max)
{
max=k;
}
}
cout<<f<<' '<<g<<' '<<max<<'\n';
}
return 0;
}
To explain my code, I'm using simple recursion.
The input is taken as i, j and is preserved as it is using f, g respectively.
i and j are swapped explicitly using temp. max is set 0 in every test case. k is used to hold the result sent by length function l() and is tested with max which stores maximum length till now.
My solution passes all the given trivial test cases in the problem.
It even passes all the tricky test cases which involve i greater than j and i==j
The problem hides integer overflow by giving incomplete information about requirement of long. I even handled that. The output rquires i, j in same order. The input gives no explicit end. I handled all of them. But still am getting wrong answer.
Your code is okay.
The only problem is your input handling untill End of File.
Just change while(!cin.eof()) to while(cin>>i>>j). You will get AC :)
May be problem with '\n'? Try to use cout<<f<<' '<<g<<' '<<max<<endl;

Optimization of C++ code

This is my solution to Spoj 11373. Coke madness
#include <cstdio>
int main(){
int T; scanf("%d",&T);
for(int j = 1; j <= T; j++){
int n;
scanf("%d",&n);
long long sum = 0, small = 0;
int t;
for(int i = 0; i < n; i++) {
scanf("%d",&t);
sum += t;
if( sum < small) small = sum;
}
printf("Scenario #%d: %lld\n", j, -1*small+1);
}
}
The problem is simple. This solution takes 0.12 seconds on Spoj, though there are 0.01 second solutions. I am curious what optimizations may be done to this code to get faster. I thought -1*small+1 may be got using bit-wise operations but didn't find how. Also I can't get rid of long long since sum may exceed int.
You're making way too many I/O calls. Read the whole file at once, and then parse it, then create your output, and then write it all at once.

Sum of all primes under 2 million

I made a program that returns the sum of all primes under 2 million. I really have no idea what's going on with this one, I get 142891895587 as my answer when the correct answer is 142913828922. It seems like its missing a few primes in there. I'm pretty sure the getPrime function works as it is supposed to. I used it a couple times before and worked correctly than. The code is as follows:
vector<int> getPrimes(int number);
int main()
{
unsigned long int sum = 0;
vector<int> primes = getPrimes(2000000);
for(int i = 0; i < primes.size(); i++)
{
sum += primes[i];
}
cout << sum;
return 0;
}
vector<int> getPrimes(int number)
{
vector<bool> sieve(number+1,false);
vector<int> primes;
sieve[0] = true;
sieve[1] = true;
for(int i = 2; i <= number; i++)
{
if(sieve[i]==false)
{
primes.push_back(i);
unsigned long int temp = i*i;
while(temp <= number)
{
sieve[temp] = true;
temp = temp + i;
}
}
}
return primes;
}
The expression i*i overflows because i is an int. It is truncated before being assigned to temp. To avoid the overflow, cast it: static_cast<unsigned long>( i ) * i.
Even better, terminate iteration before that condition occurs: for(int i = 2; i*i <= number; i++).
Tested fixed.
Incidentally, you're kinda (un)lucky that this doesn't produce extra primes as well as missing some: the int value is signed, and could be negative upon overflow, and by my reading of §4.7/2, that would cause the inner loop to skip.
You may be running into datatype limits: http://en.wikipedia.org/wiki/Long_integer.
This line is the problem:
unsigned long int temp = i*i;
I'll give you a hint. Take a closer look at the initial value you give to temp. What's the first value you exclude from sieve? Are there any other smaller multiples of i that should also be excluded? What different initial value could you use to make sure all the right numbers get skipped?
There are some techniques you can use to help figure this out yourself. One is to try to get your program working using a lower limit. Instead of 2 million, try, say, 30. It's small enough that you can calculate the correct answer quickly by hand, and even walk through your program on paper one line at a time. That will let you discover where things start to go wrong.
Another option is to use a debugger to walk through your program line-by-line. Debuggers are powerful tools, although they're not always easy to learn.
Instead of using a debugger to trace your program, you could print out messages as your program progressed. Say, have it print out each number in the result of getPrimes instead of just printing the sum. (That's another reason you'd want to try a lower limit first — to avoid being overwhelmed by the volume of output.)
Your platform must have 64-bit longs. This line:
unsigned long int temp = i * i;
does not compute correctly because i is declared int and the multiplication result is also int (32-bit). Force the multiplication to be long:
unsigned long int temp = (unsigned long int) i * i;
On my system, long is 32-bit, so I had to change both temp and sum to be unsigned long long.