This question already has answers here:
Big array gives segmentation error in C
(4 answers)
Closed 9 years ago.
This program is to find the prime number which is is the sum of most number of consecutive prime numbers. When I set the value of LIMIT to 50 100 or even 1000, the correct values are obtained. But if I take the value of LIMIT greater than 0.3 million the program crashes. What is the reason behind this problem and how can I solve it?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define LIMIT 300000
//binary search function
int Bsearch(long long int *arr,long long int low,long long int high,long long int search)
{
if(high<low)
return 0;
long long int mid = (low+high)/2;
if(search<arr[mid])
{return(Bsearch(arr,low,mid-1,search));}
else if(search>arr[mid])
{return(Bsearch(arr,mid+1,high,search));}
else if(search==arr[mid]) return 1;
else return 0;
}
int main()
{
long int arr[LIMIT];
arr[0]=0;arr[1]=1;
for(long long int i=2;i<=LIMIT;i++)
{arr[i]=1;}
long long index=2;
for(long long int i=3;i<=LIMIT;i++,index++)
{
for(long long int j=2;j<=sqrt(i);j++)
{
if(i%j==0)
{arr[index]=0;}
}
}
long long int count=0;
//calculate total primes
for(long int A=0;A<LIMIT;A++)
{
if(arr[A]==1)
count++;
}
//all primes stored in seperate primes array
long long int primes[count];
for(long int A=0,index=0;A<LIMIT;A++)
{
if(arr[A]==1)
{
primes[index++]=A+1;
}
}
long long int primes_sum[count];
primes_sum[0]=primes[0];
for(long long int B=1;B<count;B++)
{primes_sum[B]=primes_sum[B-1]+primes[B];}
for(long long int i =0;i<(sizeof(primes)/sizeof(long long int));i++)
{
printf("\nprime number : %lld\tprimes_sum : %lld",primes[i],primes_sum[i]);
}
struct ultimata
{
long long int num_of_primes;
long long int prime_number;
}final;
final.num_of_primes=0;final.prime_number=0;
for(long long int j=(sizeof(primes_sum)/sizeof(long long int))-1;j>=2;j--)
{
for(long long int i=j-2;i>=1;i--)
{
long long int search_term = primes_sum[j]-primes_sum[i];
printf("\nsearch term : %lld (primes_sum[%lld]-primes_sum[%lld])",search_term,j,i);
if(search_term>LIMIT)
break;
if(Bsearch(primes,0,(sizeof(primes)/sizeof(long long int)),search_term))
{
printf("\nfound! : %lld terms : %lld",search_term,j-i-1);
if((j-i-1)>final.num_of_primes)
{
printf("\nfound! : %lld",search_term);
final.prime_number=search_term;
final.num_of_primes=j-i-1;
}
}
}
}
printf("Largest prime number : %lld",final.prime_number,final.num_of_primes);
return 0;
}
I think one of your problems is in these lines (multiple times in other places, too):
long int arr[LIMIT];
...
for(long long int i=2;i<=LIMIT;i++)
{arr[i]=1;}
Your array has LIMIT entries, but you try to write to entry LIMIT+1. C starts with array index 0 and ends with size-1.
I don't know why it works for smaller values of LIMIT.
Related
I need to implement the karatsuba algortihm into a c code for my homework and I did my research and came up with the following code:
long int karatsuba(long int x,long int y)
{
if((x<10)||(y<10)) \\if the numbers have 1 digit, I just multiply them
return x*y;
else
{
long int a, b, c, d, ac, bd, z;
int n=uzunluk(x);
a=floor(x/ust(10, ceil(n/2)));
b=x%ust(10, ceil(n/2));;
c=floor(y/ust(10, ceil(n/2)));
d=y%ust(10, ceil(n/2));;
ac=a*c;
bd=b*d;
z=(a+b)*(c+d)-ac-bd;
long int res=ust(10, 2*ceil(n/2))*ac+ust(10, ceil(n/2))*z+bd;
return res;
}
}
int main(void)
{
printf("%ld", karatsuba(837487, 368498));
return 0;
}
ust(x, n) is the function to get the power of number x:
long int ust(long x, long n)
{
long int res=1;
int i;
for(i=0; i<n; i++)
{
res*=x;
}
return res;
}
And the uzunluk(x) gets the number of digits in the given input:
int uzunluk(long int x)
{
int lx;
while(x>0)
{
x/=10;
lx+=1;
}
return lx;
}
the problem is this code prints nothing :D
I would be glad if someone could spot the mistake I made.
So it comes out the problem was 7 digits numbers' multiplication does not result proper under the long integer identification. As I changed it to long long int, it started working properly. Thank you all for your help
My code for finding 10th decimal digit of square root of 2.
#include <stdio.h>
unsigned long long int power(int a, int b);
unsigned long long int root(int a);
int main()
{
int n;
n=10;
printf("%llu \n",root(n));
return 0;
}
unsigned long long int power(int a, int b)
{
int i;
unsigned long long int m=1;
for (i=1;i<=b;i++)
{
m*=a;
}
return m;
}
unsigned long long int root(int a)
{
unsigned long long int c=1;
int counter=1;
while(counter<=a)
{
c*=10;
while(power(c,2)<=2*power(10,2*counter))
{
c++;
}
c-=1;
counter++;
}
return c;
}
I have tried the same algorithm in python. It can find the 10th decimal digit of $sqrt{2}$ immediately.
However, while doing C, I have waited for 10 mins but without a result.
Python handles big numbers for you. [1]
Although, as you say that you are getting the answer "immediately", your algorithm in python is not probably the same as the one you used in C.
#bruno's answer already explains why you are not getting the expected results in C.
[1] Handling very large numbers in Python
Exceed the range that the data can represent. when counter is equal to 10,2*power(10,2*counter) exceeds the range that unsigned long long int can represent. Python supports large number calculations, unlimited digits
you have overflow(s)
when counter values 10 you try to compute power(10,20) but even long long on 64 bits are not enough large, so you loop in
while(power(c,2)<=2*power(10,2*counter)){
c++;
}
for a long time (may be without ending)
Having long long on 64 bits allows to compute the result for n valuing up to 9
I was practising dynamic programming on SPOJ. I am stuck on this problem named AGS. Below is my code. It is giving runtime error on SPOJ but is running perfectly fine on my computer. Please help
#include<stdio.h>
long long mypow(long long base,long long exp,long long mod,long long log[])
{
if(log[exp]!=0)
return log[exp];
if(exp==0)
return 1;
if(exp==1)
return base%mod;
long long ans = ((base%mod) * mypow(base,exp-1,mod,log))%mod;
log[exp]=ans;
return ans;
}
long long gpsum(long long r,long long k,long long mod,long long log[])
{
if(k==0)
return 1;
if(k==1)
return 1+r;
long long ans=(mypow(r,k,mod,log)+gpsum(r,k-1,mod,log))%mod;
return ans;
}
int main()
{
long long i,t,k,a,d,r,n,mod,p,q,ans;
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld %lld",&a,&d,&r);
scanf("%lld %lld",&n,&mod);
long long log[n/2];
for(i=0;i<n/2;i++)
log[i]=0;
if(n==1)
{
ans=a;
}
else if(n%2==0)
{
k=(n-2)/2;
p=mypow(r,k,mod,log);
q=gpsum(r,k,mod,log);
ans=(((p%mod)*(a%mod))%mod+((q%mod)*(d%mod))%mod)%mod;
}
else
{
k=(n-3)/2;
p=r*mypow(r,k,mod,log);
q=r*gpsum(r,k,mod,log);
ans=(((p%mod)*(a%mod))%mod+((q%mod)*(d%mod))%mod)%mod;
}
printf("%lld\n",ans);
}
return 0;
}
It looks like the line long long log[n/2]; causing the error. For n = 12345678 (from the sample input in the comments) it will try to allocate around 6M of long long which is about 50Mb on the stack. Which is, I am guessing, too big for the online multi user compilers. The following code will prove this claim:
#include<stdio.h>
#define MAX 7000000
int main()
{
volatile long long v[MAX];
long i;
for ( i=0; i<MAX; i++ )
v[i]=i+1;
printf("Hello");
return 0;
}
The value of MAX as stated will give the error on ideone. Reducing the value, say to 700000 will remove the error (don't mind the volatile and the loop exercises, they are there to trick on optimizer).
A possible solution would be allocating this memory statically, as a global variable - outside the main function, such that it will go to the .data section, and not to the stack. This solution:
#include<stdio.h>
#define MAX 7000000
volatile long long v[MAX];
int main()
{
long i;
for ( i=0; i<MAX; i++ )
v[i]=i+1;
printf("Hello");
return 0;
}
works just fine even with larger numbers.
I had written this code which has the recursive function differ, when I run it, using the printf statements I notice that the code executes in the proper direction and I get the required value printed by the printf statement at the end of differ function but that value is not immediately returned instead the recursion goes again in the reverse direction and returns a wrong value. I have been struggling to debug it but I do not understand why it does not return immediately after it executes the last printf statement. Please help!!
To run enter:
5 3 1
0 3 8 5 12
1 3
as the input
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
long long int df;
long long max(long long int a,long long int b)
{
long long int maxi;
maxi = a>b ? a:b;
return maxi;
}
long long min(long long int x,long long int y,long long int *a)
{
long long int mini;
mini = a[x]<a[y] ? (x+1):(y+1);
return mini;
}
long long differ(long long int n1,long long int n2,long long int *a,long long int k,long long int n)
{
long long int df,i;
df=a[n1-1]-a[n2-1];
df=abs(df);
printf("%lld\n",df);
if(df>k)
{
for(i=0;i<n;i++)
{
if(max(a[n1-1],a[n2-1])>a[i] && (max(a[n1-1],a[n2-1])-a[i])<=k)
{
printf("%lld %lld\n",a[i],a[min(n1-1,n2-1,a)-1]);
differ(i+1,min(n1-1,n2-1,a),a,k,n);
return df; //Even this does not work
}
}
}
printf("%lld 90909\n",df);/*This does print a required value but changes again and returns a wrong value finally.*/
return df;
}
int main()
{
long long int n,k,p,f1,f2,d=0,i,j;
scanf("%lld",&n);
long long int a[n];
scanf("%lld",&k);
scanf("%lld",&p);
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
while(p-- > 0)
{
scanf("%lld",&f1);
scanf("%lld",&f2);
printf("%lld df\n",d);
d = differ(f1,f2,a,k,n);
printf("%lld diff",d);
if(d<=k)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}
Assigning the recursive function to df would solve the problem, that is
df=differ(i+1,min(n1-1,n2-1,a,k,n);
Hope it helps someone who is struggling with this small mistake during recursion.
We are given an array a[1..N]. For each element a[i] in the array, we note down the sum of all the elements which are smaller and occur before the present element. I need to calculate the total sum for every element in the array.
Constraints:
1<=N<=10^5
All elements will be between 0 and 10^6.
Here is the link to my question: http://www.spoj.com/problems/DCEPC206/. I'm using the approach shown below, but I'm getting TIME LIMIT EXCEEDED error on SPOJ. How can I improve my solution?
include
int main()
{
long n,a[100000],i,j,sum;
printf("enter the number of elements");
scanf("%ld",&n);
printf("enter the elements of the array");
for(i=0;i<n;i++)
scanf("%ld",&a[i]);
sum=0;
for(i=1;i<n;i++)
for(j=i-1;j>=0;j--)
if(a[i]>a[j])
sum+=a[j];
printf("\n%ld",sum);
return 0;
}
Yours is a trivial implementation which takes time of the order of O(n^2) but for the solution to get accepted you have to use Divide and Conquer as you do in Merge Sort which takes only O(NLogN) time compared to simpler sorting algorithms like Bubble Sort,etc.
For this you simply can change the Mergesort implementation a little bit simply by adding 2-3 lines of code in it. For understanding this better go through question of counting inversions in an array.(http://www.geeksforgeeks.org/counting-inversions/) Then you will realize you simply have to consider pairs opposite in nature to inversion and add all the smaller elements of all such pairs . For example - in an array 1,4,2,5 consider 4,2 is inversion but we have to consider pairs like 2,5 and 1,2 to get the solution. In every such pair keep adding the left no. ( Think hard about how it is doing our job !! )
For your reference go thoroughly through this merge sort code in which i have small changes to get a correct accepted solution.(sum variable stores the resultant value)
#include <stdio.h>
#include <stdlib.h>
long long int sum;
void merge(long long int c[],long long int arr[],long long int start,long long int middle,long long int end)
{
long long int i=0,j=start,k=middle;
while((j<middle)&&(k<end))
{
if(arr[j]<arr[k])
{
sum=sum+((end-k)*arr[j]);
c[i]=arr[j];
i++;j++;
}
else
{
c[i]=arr[k];
i++;k++;
}
}
while(j<middle)
{
c[i]=arr[j];
i++;
j++;
}
while(k<end)
{
c[i]=arr[k];
i++;
k++;
}
}
void msort(long long int arr[],long long int start,long long int end)
{
long long int middle=(start+end)/2;
if((end-start)==1)
{ return ;
}
msort(arr,start,middle);
msort(arr,middle,end);
long long int *c;
c=(long long int*)malloc(sizeof(long long int)*(end-start));
merge(c,arr,start,middle,end);
long long int i,j=0;
for(i=start;i<end;i++)
{
arr[i]=c[j];
j++;
}
}
void swap (long long int x[],long long int m,long long int n)
{
long long int t= x[m];
x[m]=x[n];
x[n]=t;
}
int main()
{
int t,i;
long long int n,*arr,j;
scanf("%d",&t);
for(i=0;i<t;i++)
{
scanf("%lld",&n);
arr = ( long long int * ) malloc ( sizeof(long long int) * n + 10);
for(j=0;j<n;j++)
{
scanf("%lld",&arr[j]);
}
sum=0;
msort(arr,0,n);
// for(j=0;j<n;j++)
// printf("%lld ",arr[j]);
printf("%lld\n",sum);
}
return 0;
}