COINS on SPOJ — Every time getting a runtime error (SIGSGEV) - c

/***********************************************************************************************************************************COINS problem on SPOJ."http://www.spoj.com/problems/COINS/".Every time I'm getting a runtime error (SIGSGEV). Please help with what's wrong. It runs well on my machine and I can't find any problem. It gives correct output as well. But in SPOJ it is not getting accepted.
***********************************************************************************************************************************/
#include<stdio.h>
long long arr[1000000]; /* Is this large number ok?*/
long long coins(long long n)/*Used recursion*/
{
if(n==0)
return 0;
if(arr[n]!=0)
return arr[n];
long long a,b,c,sum;
a=n/2;
b=n/3;
c=n/4;
sum=coins(a)+coins(b)+coins(c);
if(sum>n)
{
arr[n]=sum; /*Dynamic programming*/
return sum;
}
else
{
arr[n]=n; /*Dynamic programming*/
return n;
}
}
int main()
{
long long n;
while(scanf("%lld",&n))//Have doubt in this. Should it be while(scanf(...)!=EOF)
{
long long dollar=coins(n);
printf("%lld\n",dollar);
}
return 0;
}

The problem show that n <= 1000000000, and in function coins, you will use arr[n], which will absolutely be out of the range of 1000000.
But I think you are on the right way~
A hint: consider 2^32 > 1000000000, so how many sub-problems?

Related

What is the cause of this segmentation fault: 11 error?

I'm trying to write a program in C that reads in a positive integer of up to 20 digits. It should output the smallest palindromic number that is higher than the input. A palindromic number is one that is the same when its digits are reversed (e.g, 98789 is a palindrome, 12344321 is a palindrome, 12345 is not a palindrome as it becomes 54321 when reversed). A sample run, for example, would take 17 as an input and output 22. However, when I run the program and place an input, a segmentation fault: 11 error occurs. Please note that I'm not an experienced programmer, so the code might seem ugly:
#include <stdio.h>
unsigned long reversed(unsigned long palindrome);
int main() {
unsigned long palindrome;
scanf("%lu", &palindrome);
while(1) {
palindrome++;
if (palindrome == reversed(palindrome)) {
printf("%lu", reversed(palindrome));
break;
}
}
}
unsigned long reversed(unsigned long palindrome) {
int size = 0;
unsigned long copy = palindrome;
while(copy != 0) {
copy /= 10;
size++;
}
int count = 0;
unsigned long arr[size];
while (palindrome != 0) {
arr[count] = palindrome % 10;
count++;
}
unsigned long reverse = 0;
for (int i = 0; i < size; i++) {
reverse *= 10;
reverse += arr[i];
}
return reverse;
}
The error seems to suggest that I'm accessing a memory location that I shouldn't be accessing, but I don't understand the actual cause of this. Does it have to do with the unsigned longs or the array? I appreciate any advice. Thanks.
The error seems to be caused by this loop probably.
while (palindrome != 0) {
arr[count] = palindrome % 10;
count++;
}
you are not changing the value of palindrome inside this loop, but the value of count is increasing causing you to access a memory which is out of bounds when count becomes greater then size

Finding biggest prime number in user-inputted number - C

I have a problem with my code. The topic is to write a C program which finds biggest prime number in the number inputted by user.
Ex.:
Enter number: 46656665326
Output: 66566653
This is my code:
#include <stdio.h>
#include <stdlib.h>
int is_prime(unsigned long long a)
{
if(a<=1)
return 0;
if(a==2)
return 1;
for(unsigned long long p=2; p<a; p++)
if(a%p==0)
return 0;
return 1;
}
unsigned long long find_largest_prime_number(unsigned long long number)
{
unsigned long long prime=0;
int count=0;
unsigned long long count2=1;
unsigned long long pom=0;
unsigned long long pom3=0;
pom3=number;
while(pom3!=0)
{
count++;
pom3/=10;
}
count++;
int pom_1=0;
while(pom_1<count)
{
count2*=10;
pom_1++;
}
pom=number;
while(count2>=10)
{
unsigned long long pom2=pom;
while(pom2!=0)
{
if(is_prime(pom2))
if(pom2>prime)
prime=pom2;
pom2/=10;
}
count2/=10;
pom=pom%count2;
}
return prime;
}
int main()
{
unsigned long long x=0;
printf("Enter number: ");
int n1=scanf("%llu", &x);
if(n1!=1)
{
printf("incorrect input");
return 1;
}
printf("%llu", find_largest_prime_number(x));
return 0;
}
The problem is it works with max 13-digit number but it freezes when the input number has more than 13 digits.
Ex. it freezes when I enter: 215911504934497
Please help, what's wrong with the code?
The reason for block boils down to this:
int is_prime(unsigned long long a)
{
...
for(unsigned long long p=2; p<a; p++)
if(a%p==0)
return 0;
return 1;
}
If you enter 215911504934497 then the find_largest_prime_number will call is_prime(215911504934497). 215911504934497 is a big number, and doing a%p for each p from 2 to 215911504934497 is cpu expensive (I think at least you could p < a/2). Your program get's stuck in this loop. You can observe that by doing a simple printf inside it:
int is_prime(unsigned long long a)
{
...
for(unsigned long long p=2; p<a; p++) {
printf("%lld %lld\n", p, a);
if(a%p==0)
return 0;
}
return 1;
}
Your code is perfectly correct. It is simply terribly inefficient and therefore takes very, very long time just to find out if a single large number is prime.
Here is better version of is_prime:
It tests divisors only up to the square root of the number to be tested.
It only tests odd divisors, if the number is not divisible by two, it's pointless to test if it's divisible by 4, 6, 8 etc.
// long long integer square root found somewhere on the internet
unsigned long long isqrt(unsigned long long x)
{
unsigned long long op, res, one;
op = x;
res = 0;
/* "one" starts at the highest power of four <= than the argument. */
one = 1LL << 62; /* second-to-top bit set */
while (one > op) one >>= 2;
while (one != 0) {
if (op >= res + one) {
op -= res + one;
res += one << 1; // <-- faster than 2 * one
}
res >>= 1;
one >>= 2;
}
return res;
}
int is_prime(unsigned long long a)
{
if (a <= 1 || a == 2 || a % 2 == 0)
return 0;
unsigned long long count = 0;
unsigned long long limit = isqrt(a) + 1;
for (unsigned long long p = 3; p < limit; p += 2)
{
if (a % p == 0)
return 0;
}
return 1;
}
Further optimisations are of course possible. E.g. it is also pointless to test for multiples of 3 if the number was not divisible by 3 etc. Also if you want to find a range of prime numbers there are probably other approaches to be taken into account.
Focusing on square root finally solved the issue.
is_prime should be looking like that:
int is_prime(unsigned long long a)
{
int i=0;
int count=0;
int test=0;
int limit=sqrt(a)+1;
if(a<=1)
return 0;
if(a==2)
return 1;
if(a%2==0)
test=1;
else
for(i=3; i<limit && !test; i+=2, count++)
if(a%i==0)
test=1;
if(!test)
return 1;
else
return 0;
}
As mentioned by other contributors, and in the comments, your code is "crashing" simply because it is inefficient.
Many of the other contributors have used a more efficient way of checking whether a number is prime by checking that number against its divisors.
HOWEVER, this is not the most efficient manner to go about doing it, especially if you are whether multiple numbers are prime.
In order to make it even faster, I suggest an implementation of the Sieve of Eratosthenes:
#define MAX_N 4294967296 //idk how big of an array your computer can actually handle. I'm using 2^32 here.
//Declare as a global variable for extra memory allocation
//unsigned char is used as it is only 1 byte (smallest possible memory alloc)
//0 for FALSE, 1 for TRUE.
unsigned char is_prime[MAX_N+1];
//Populate the is_prime function up to your input number (or MAX_N, whichever is smaller)
//This is done in O(N) time, where N is your number.
void performSieve(unsigned long long number){
unsigned long long i,j;
unsigned long long n = (number>MAX_N)?MAX_N:number; //quick way (ternary operator): "whichever is smaller"
//Populating array with default as prime
for(i=2; i<=n; i++) is_prime[i] = 1;
for(i=4; i<=n; i+=2) is_prime[i] = 0; //all even numbers except 4 is not prime
for(i=3; i<=n; i+=2){
if(is_prime[i] == 1)
for(j=i*i;j<=n;j+=i){ //all the multiples of i except i itself are NOT prime
is_prime[i] == 0;
}
}
}
//isPrime function
unsigned char isPrime(unsigned long long n){
if(n<=1) return 0; //edge cases
//Check if we can find the prime number in our gigantic sieve
if(n<=MAX_N){
return is_prime[n]; //this is O(1) time (constant time, VERY FAST!)
}
//Otherwise, we now use the standard "check all the divisors" method
//with all the optimisations as suggested by previous users:
if(n%2==0) return 0; //even number
//This is from user #Jabberwocky
unsigned long long limit = isqrt(a);
for (unsigned long long p = 3; p <= limit; p += 2) {
if (a % p == 0) return 0;
}
return 1;
}

Right implementation of two functions related to fibonacci and prime numbers

I have a very long question and some part of the question, involves two functions named gp(a,t) and fibo(a,t).
gp(a,t) gets two integer numbers a ,t and must return the smallest prime number that is greater than or equal to (t/100)*a
fibo(a,t) gets two integer numbers a,t and must return the biggest member of fibonacci series that is less than or equal to (t/100)*a. (We consider 0 as the first member of fibonacci series in this problem, so it is 0 1 1 2 3 5 8 13 ...)
(The problem didn't mention that we must save that (t/100)*a as float but according to its examples, it must be considered a float for example if it is 3.5 then gp must return 5 and not 3.)
I implemented this functions but in some unknown test cases, it fails and so I want to know which part of my functions are wrong. Is there any a,t that my functions give wrong answer for them?
Note: I defined everything as long long because the main very long part of the question said to use long long because the numbers will get big.
Note 2: It doesn't give time limit error, so there is no problems like infinite loop or not optimised calculation of prime numbers.
My functions: (written in c)
long long int primeCheck(long long int a)
{
if (a==1 || a ==0)
{
return 0;
}
long long int isPrime = 1;
;
for (long long int i =2;i*i<=a;i++)
{
if (a%i==0)
{
isPrime=0;
break;
}
}
return isPrime;
}
long long int fibo (long long int a, long long int t)
{
float check = (t*1.00/100)*1.00*a;
if (check ==0)
{
return 0;
}
else if (check==1)
{
return 1;
}
long long int f_n_2 = 0;
long long int f_n_1 = 1;
long long int f_n=0;
while (f_n<=check)
{
f_n = f_n_2 + f_n_1;
f_n_2 = f_n_1;
f_n_1 = f_n;
if (f_n > check)
{
return f_n_2;
}
else if (f_n == check)
{
return f_n;
}
}
return 0;
}
long long int gp (long long int a , long long int t)
{
float check = (t*1.00/100)*1.00*a;
long long int i=ceil(check);
while(1)
{
if (primeCheck(i) )
{
return i;
}
i++;
}
return 0;
}
PS1. The problem is Solved. The issue was in the judge system and the code is just fine!

Large array causing segmentation fault

I wrote a code with the following specified constraints:
Hence I chose the data types for my variables accordingly.
However my code fails all the test cases saying segmentation fault. (possibly because the array size they input is very large.) Is there a way to get more stack space or heap space? or get around this problem by declaring the array in some other way? Is there something else that's causing segmentation fault? Other people have solved this problem, so there must be a way.
this is the code:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
long find_index(long x, long *cost, long n, long used_index)
{
long i;
for(i = 0; i < n; i++)
if(*(cost + i) == x && i != used_index)
return (i+1);
return 0;
}
int purchase(long *cost, long n, long money)
{
long i, index;
for(i = 0; i < n ;i++)
{
index = find_index((money - *(cost - i)),cost,n,i);
if(index)
{
printf("%ld %ld\n",i+1,index);
break;
}
}
free(cost);
return 0;
}
int main(void)
{
int t;
long *cost, money, n, i;
scanf("%d",&t);
while(t > 0)
{
scanf("%ld",&money);
scanf("%ld",&n);
cost = (long *)malloc(n*sizeof(long));
for(i = 0; i < n; i++)
scanf("%ld",(cost+i));
purchase(cost,n,money);
t--;
}
return 0;
}
this is one of the hidden test cases they check for:
35 // this is t
299701136 // this is money
2044 // this is n
50293811 136626876 58515785 59281065 ..... goes on forever...
That's a lot of complex code to analyze, so instead of giving you a fish, I'll try to give you a rod.
Whatever platform, compiler and IDE you're using, there probably is a way to perform step-by-step debugging of your program at runtime. Maybe your assumptions are wrong and the allocation size is not causing this problem.
Learning basics of debugging is really great tool in programmer's hands. Here is an example tutorial video: https://www.youtube.com/watch?v=9gAjIQc4bPU
These changes in the code fix the issue of array index out of bounds problem, Hence the segmentation fault issue:
if((money - *(cost + i)) < n)
index = find_index((money - *(cost + i)),cost,n,i);
The constraints mentioned cause no issue.

SPOJ COINS DP and Recursive Approach

I have recently started solving DP problem and I came across COINS. I tried to solve it using DP with memoization and it works fine if I use int array(I guess).
Here is my approach(few modifications left):
#include <stdio.h>
#include <stdlib.h>
int dp[100000];
long long max(long x, long y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int n,i;
scanf("%d",&n);
dp[0]=0;
for(i=1;i<=n;i++)
{
dp[i]=max(i,dp[i/2] + dp[i/3] + dp[i/4]);
}
printf("%d\n",dp[n]);
return 0;
}
But I don't understand as soon as I use long long array I get SIGSEGV.
I searched and there seems to be a recursive solution that I am not understanding.
Can someone help me out here?
The limits say n<=10e9, array size of which will always result in memory overflow and hence, SIGSEGV. It does not matter what is the type of your dp-array.
There are yet other errors in your code. Firstly, there are test-cases, which you have to read till EOF. Secondly, since the limits are 10e9, you are looping n times !! Surely TLE.
Now, for the recursive solution, using memoization:
Firstly, save the answer values till 10e6 in the array. Will help save time. It can be done as:
long long dp[1000000] = {0};
for(int i = 1; i < 1000000; i++){
dp[i] = max(i, dp[i/2] + dp[i/3] + dp[i/4]);
}
Now, for any input n, find the solution as,
ans = coins(n);
Implement coins function as:
long long coins(long long n){
if (n < 1000000)
return dp[n];
return coins(n/2) + coins(n/3) + coins(n/4);
}
Why this recursive solution works:
It is very obvious that answer for all n >= 12 will be ans[n/2] + ans[n/3] + ans[n/4], so for n > 10e6, that is returned.
The base condition for the recursion is just to save time. You can also return it for 0, but then then you will have to take care of corner cases. (You get my point there)
Exact code:
#include<stdio.h>
long long dp[1000000] = {0};
long long max(long long a, long long b){
return a>b?a:b;
}
long long coins(long long n){
if (n < 1000000)
return dp[n];
return coins(n/2) + coins(n/3) + coins(n/4);
}
int main(){
for(long long i = 1; i < 1000000; i++){
dp[i] = max(i, dp[i/2] + dp[i/3] + dp[i/4]);
}
long long n;
while(scanf("%lld",&n) != EOF){
printf("%lld\n", coins(n));
}
return 0;
}

Resources