stack overflow c++ - c++

So i', trying to solve a task.
a already have code, but system outs, "stack overflow"
i'm new in c++ and my english isn't good so i'm sorry for misunderstanding =)
#include <iostream>
using namespace std;
int main (){
int n;
int x;
int k = 0; // счетчик для рабочего массива
int a [200000];
scanf("%d\n",&n);
for (int i = 0; i< n; ++i){
std::cin >> x;
if (x > 0){
k++;
a[k] = x;
}else if(x == 0){
for (int q = 1; q <= k; ++q){ // копирование
a[k+q] = a[q];
}
k *= 2;
}else{
printf("%d %d\n",a[k],k);
k--;
}
}
system("pause");
}
looks like algorithm works correctly, but only problem is stack. thanks a lot!

Root Cause:
As you guessed correctly, the stack is limited and seems your allocation is large enough to be catered through it. This is not an language syntax error so it does not warrant a compilation error but it results in a run time exception thus causing a crash.
Solution 1:
You can make the array global, the allocation of an global array is not on stack so it should work fine for you:
int a [200000];
int main()
{
.....
}
Solution 2:
You could use a std::vector
Solution 3:
You can use dynamic allocation through new.

Statement int a [200000]; attempts to allocate more memory on the stack than will fit, which caused stack overflow. Some people recommend that arrays larger than a few kilobytes should be allocated dynamically instead of as a local variable. Please refer to wikipedia: http://en.wikipedia.org/wiki/Stack_overflow#Very_large_stack_variables

3 changes I can see.
1 - allocating on the stack more than the stack can handle.
2 - k should always pointing to the next free space so you need to update than increase it.
3 - the index are starting from "0" both for the "q" for.
Fixed code:
#include <iostream>
using namespace std;
int a [200000];
int main (){
int n;
int x;
int k = 0; // счетчик для рабочего массива
scanf("%d\n",&n);
for (int i = 0; i< n; ++i){
std::cin >> x;
if (x > 0)
{
a[k] = x;
k++; //<< change 1
}
else if (x == 0)
{
for (int q = 0; q <= k; ++q) //<<change 2
{ // копирование
a[k+q] = a[q];
}
k *= 2;
}
else
{
printf("%d %d\n",a[k],k);
k--;
}
}
system("pause");
}

Related

C++ Segmentation Fault (SIGSEGV)

I have a problem statement.
Given an even number A ( greater than 2 ), return two prime numbers whose sum will be equal to given number.
The following solution code runs fine for all small and medium inputs but fails for a very large input 16777214. It is a segmentation fault and I tried to read this article on it but I cannot figure out what my program is doing wrong, since it is working for other inputs or what should I fix here. I'm new to C++;
#include <iostream>
#include <vector>
using namespace std;
void form_sieve(int A, int* prime){
for(int c = 0; c < A; c++)
prime[c] = 1;
prime[0] = 0;
prime[1] = 0;
for(int p = 2; p * p <= A; p++){
if(prime[p] == 1){
// update all multiples of p
for(int i = p * p; i <= A; i += p)
prime[i] = 0;
}
}
}
void primesum(int A) {
// find prime numbers less than A
// use sieve method
int prime[A + 1];
form_sieve(A, prime);
vector<int> result;
// for(int c = 0; c <= A; c++)
// cout << prime[c] << "\n";
for(int i = 2; i <= A; i++){
if(prime[i]){
if(i + i == A){
result.push_back(i);
result.push_back(i);
break;
}
else if(prime[A - i]){
result.push_back(i);
result.push_back(A - i);
break;
}
}
}
// cout << result.size();
for(vector<int>::iterator ptr = result.begin(); ptr < result.end(); ptr++){
cout << *ptr << "\n";
}
// return result;
}
// Driver Code
int main()
{
primesum(16777214);
}
You need to allocate new memory.
A user2717954 already suggested using a vector for primes, which is the best way to fix this.
If you wanted to use arrays, you could change int prime[A+1] to int* prime = new int[A+1];. Then delete [] prime; after you're finished using it at the end of the function.
When I do this, the program doesn't segfault. You must allocate dynamic memory and clean up after you're done since the program doesn't know how much memory to allocate since the size A + 1 isn't known at compile-time.
However, vectors will, of course, resize as needed so you won't have to worry about dynamic memory.

C++ Counting inversions in array, Fatal Signal 11 (BIT)

I was given this challenge in a programming "class". Eventually I decided to go for the "Binary Indexed Trees" solution, as data structures are a thing I'd like to know more about. Implementing BIT was somewhat straight forward, things after that - not so much. I ran into "Fatal Signal 11" when uploading the solution to the server, which, from what I've read, is somewhat similar to a Null pointer exception. Couldn't figure out the problem, decided to check out other solutions with BIT but stumbled upon the same problem.
#include<iostream>
using namespace std;
/* <BLACK MAGIC COPIED FROM geeksforgeeks.org> */
int getSum(int BITree[], int index){
int sum = 0;
while (index > 0){
sum += BITree[index];
index -= index & (-index);
}
return sum;
}
void updateBIT(int BITree[], int n, int index, int val){
while (index <= n){
BITree[index] += val;
index += index & (-index);
}
}
/* <BLACK MAGIC COPIED FROM geeksforgeeks.org> */
int Count(int arr[], int x){
int sum = 0;
int biggest = 0;
for (int i=0; i<x; i++) {
if (biggest < arr[i]) biggest = arr[i];
}
int bit[biggest+1];
for (int i=1; i<=biggest; i++) bit[i] = 0;
for (int i=x-1; i>=0; i--)
{
sum += getSum(bit, arr[i]-1);
updateBIT(bit, biggest, arr[i], 1);
}
return sum;
}
int main(){
int x;
cin >> x;
int *arr = new int[x];
for (int temp = 0; temp < x; temp++) cin >> arr[temp];
/*sizeof(arr) / sizeof(arr[0]); <-- someone suggested this,
but it doesn't change anything from what I can tell*/
cout << Count(arr,x);
delete [] arr;
return 0;
}
I am quite stumped on this. It could be just some simple thing I'm missing, but I really don't know. Any help is much appreciated!
You have condition that every number lies between 1 and 1018. So, your biggest number can be 1018. This is too much for the following line:
int bit[biggest+1];

c++ runtime error when using vectors push back and iterator

Hi I'm trying to solve a algorithm problem and when I submit my code on an online judge I keep on getting a runtime error. I have no idea why it is happening.
Here is the problem that I'm trying to solve.
The code is as follows. It works fine for the sample input and outputs in visual studio. I haven't yet met inputs and outputs that does not work well or actually meet the runtime error. Only the online judge is giving the runtime error so I can't figure out why.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int m;
int c1;
int c2;
cin >> n >> m >> c1 >> c2;
vector<int> p = {};
vector<int> q = {};
for (int i = 0; i < n; ++i)
{
int temp;
cin >> temp;
p.push_back(temp);
}
for (int i = 0; i < m; ++i)
{
int temp;
cin >> temp;
q.push_back(temp);
}
vector<int> distance = {};
for (int i = 0; i < p.size(); ++i)
{
for (int j = 0; j < q.size(); ++j)
{
distance.push_back(abs(p[i] - q[j]) + abs(c1 - c2));
}
}
sort(distance.begin(), distance.end());
int min = distance[0];
int count = 0;;
for (int i = 0; i < static_cast<int>(distance.size()); ++i)
{
if (distance[0] == distance[i])
count++;
else
break;
}
cout << min << " " << count << endl;
return 0;
}
If n and m are both the maximum allowed value of 500,000 then distance will have 500,000 * 500,000 elements which will use 1TB of memory. Due to vector growing as you push_back you could actually need around 2TB of memory in total. The online judge presumably doesn't allow you to use this much memory.
If you rethink your algorithm to not store the values of distance it will probably work.
You should lways use reserve on std::vector if you know the size in advance as it should cause the vector to allocate exactly the right amount of memory and avoid copying to new blocks of memory as the vector grows.

selection sort array run time error

This is my first time here. I really hope anyone can help me out there. So this is my problem. I keep getting run time error #2 something about a corrupt "arr". But the program runs fine until the end. I can't figure it out.
This is my code:
#include <iostream>
using namespace std;
void main(){
int arr1[3];
int temp;
//INPUT NUMBERS
for (int i=0; i<5;i++)
{
cin>>arr1[i];
}
cout<<endl;
//SORT
for(int c=0;c<5;c++)
{
for (int k=0;k<5;k++)
{
if(arr1[c]<arr1[k])
{
temp=arr1[k];
arr1[k]=arr1[c];
arr1[c]=temp;
}
}
}
for (int m=0; m<5; m++)
{
cout<<arr1[m]<<endl;
}
}
Try this out:
#include <iostream>
using namespace std;
int main()
{
int arr1[5];
int temp;
//INPUT NUMBERS
for (int i = 0; i < 5; i++) {
cin >> arr1[i];
}
cout << endl;
//SORT
for (int c = 0; c < 5; c++) {
for (int k = 0; k < 5; k++) {
if (arr1[c] < arr1[k]) {
temp = arr1[k];
arr1[k] = arr1[c];
arr1[c] = temp;
}
}
}
for (int m = 0; m < 5; m++) {
cout << arr1[m] << endl;
}
}
It compiles properly without any errors. The mistake you had made is in declaring the size of the array. If you want to store 5 in puts, you need to declare an array of size 5. Your code might work, but a good compiler will always give out an error.
The reason being that when you declare an array, you actually create a pointer to the first element of the array. And then, some memory regions are kept for this array, depending on the size. If you try to access an element that is outside these memory regions, you may encounter a garbage value.
Here's your code in ideone.

Codechef practice question help needed - find trailing zeros in a factorial

I have been working on this for 24 hours now, trying to optimize it. The question is how to find the number of trailing zeroes in factorial of a number in range of 10000000 and 10 million test cases in about 8 secs.
The code is as follows:
#include<iostream>
using namespace std;
int count5(int a){
int b=0;
for(int i=a;i>0;i=i/5){
if(i%15625==0){
b=b+6;
i=i/15625;
}
if(i%3125==0){
b=b+5;
i=i/3125;
}
if(i%625==0){
b=b+4;
i=i/625;
}
if(i%125==0){
b=b+3;
i=i/125;
}
if(i%25==0){
b=b+2;
i=i/25;
}
if(i%5==0){
b++;
}
else
break;
}
return b;
}
int main(){
int l;
int n=0;
cin>>l; //no of test cases taken as input
int *T = new int[l];
for(int i=0;i<l;i++)
cin>>T[i]; //nos taken as input for the same no of test cases
for(int i=0;i<l;i++){
n=0;
for(int j=5;j<=T[i];j=j+5){
n+=count5(j); //no of trailing zeroes calculted
}
cout<<n<<endl; //no for each trialing zero printed
}
delete []T;
}
Please help me by suggesting a new approach, or suggesting some modifications to this one.
Use the following theorem:
If p is a prime, then the highest
power of p which divides n! (n
factorial) is [n/p] + [n/p^2] +
[n/p^3] + ... + [n/p^k], where k is
the largest power of p <= n, and [x] is the integral part of x.
Reference: PlanetMath
The optimal solution runs in O(log N) time, where N is the number you want to find the zeroes for. Use this formula:
Zeroes(N!) = N / 5 + N / 25 + N / 125 + ... + N / 5^k, until a division becomes 0. You can read more on wikipedia.
So for example, in C this would be:
int Zeroes(int N)
{
int ret = 0;
while ( N )
{
ret += N / 5;
N /= 5;
}
return ret;
}
This will run in 8 secs on a sufficiently fast computer. You can probably speed it up by using lookup tables, although I'm not sure how much memory you have available.
Here's another suggestion: don't store the numbers, you don't need them! Calculate the number of zeroes for each number when you read it.
If this is for an online judge, in my experience online judges exaggerate time limits on problems, so you will have to resort to ugly hacks even if you have the right algorithm. One such ugly hack is to not use functions such as cin and scanf, but instead use fread to read a bunch of data at once in a char array, then parse that data (DON'T use sscanf or stringstreams though) and get the numbers out of it. Ugly, but a lot faster usually.
This question is from codechef.
http://www.codechef.com/problems/FCTRL
How about this solution:
#include <stdio.h>
int a[] = {5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625};
int main()
{
int i, j, l, n, ret = 0, z;
scanf("%d", &z);
for(i = 0; i < z; i++)
{
ret = 0;
scanf("%d", &n);
for(j = 0; j < 12; j++)
{
l = n / a[j];
if(l <= 0)
break;
ret += l;
}
printf("%d\n", ret);
}
return 0;
}
Any optimizations???
Knows this is over 2 years old but here's my code for future reference:
#include <cmath>
#include <cstdio>
inline int read()
{
char temp;
int x=0;
temp=getchar_unlocked();
while(temp<48)temp=getchar_unlocked();
x+=(temp-'0');
temp=getchar_unlocked();
while(temp>=48)
{
x=x*10;
x+=(temp-'0');
temp=getchar_unlocked();
}
return x;
}
int main()
{
int T,x,z;
int pows[]={5,25,125,625,3125,15625,78125,390625,1953125,9765625,48828125,244140625};
T=read();
for(int i=0;i<T;i++)
{
x=read();
z=0;
for(int j=0;j<12 && pows[j]<=x;j++)
z+=x/pows[j];
printf("%d\n",z);
}
return 0;
}
It ran in 0.13s
Here is my accepted solution. Its score is 1.51s, 2.6M. Not the best, but maybe it can help you.
#include <iostream>
using namespace std;
void calculateTrailingZerosOfFactoriel(int testNumber)
{
int numberOfZeros = 0;
while (true)
{
testNumber = testNumber / 5;
if (testNumber > 0)
numberOfZeros += testNumber;
else
break;
}
cout << numberOfZeros << endl;
}
int main()
{
//cout << "Enter number of tests: " << endl;
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
int testNumber;
cin >> testNumber;
calculateTrailingZerosOfFactoriel(testNumber);
}
return 0;
}
#include <cstdio>
int main(void) {
long long int t, n, s, i, j;
scanf("%lld", &t);
while (t--) {
i=1; s=0; j=5;
scanf("%lld", &n);
while (i != 0) {
i = n / j;
s = s + i * (2*j + (i-1) * j) / 2;
j = j * 5;
}
printf("%lld\n", s);
}
return 0;
}
You clearly already know the correct algorithm. The bottleneck in your code is the use of cin/cout. When dealing with very large input, cin is extremely slow compared to scanf.
scanf is also slower than direct methods of reading input such as fread, but using scanf is sufficient for almost all problems on online judges.
This is detailed in the Codechef FAQ, which is probably worth reading first ;)