Right implementation of two functions related to fibonacci and prime numbers - c

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!

Related

How to handle Integer overflow when calculating factorial > 31

The iterative function returns the result of a factorial operation. The code seems to break after I try to compute a number that will result in an integer overflow. How could I best handle this? Would it make sense and is it accurate? to store every iteration over the maximum limit as a power of and return the limit plus a character string describing the amount of times it can be multiplied by itself?
int ft_iterative_factorial(int nb)
{
int i;
int n;
int res;
i = 1;
n = nb;
res = nb;
while (i < nb)
{
if (nb == 1 || nb == 0)
{
res = 1;
break ;
}
res = res * (n - 1);
i++;
n--;
}
return ((nb < 0 || nb > 31) ? 0 : res);
}
Your function is really complicated.
Consider rather this implementation:
int ft_iterative_factorial(int nb)
{
int res = 1;
for (int i = 2; i <= nb; i++)
{
res = res * i;
}
return res;
}
Your test return ( nb < 0 ? 0 : res); doesn't make much sense after the loop, you should do it before the loop, and nor does if (nb == 1 || nb == 0) inside the loop. But these tests are pointless anyway in my code.
int is probably a 32 bit type and 32 bits is not enough to store 16!.
Either use long long (usually 64 bit) instead of int (but then you'd be limited at 21 or so), or handle cases where value >16 otherwise.
BTW: if you really want to be fast, don't calculate the factorial but use a lookup table, this is left as an exercise to the reader.
Either use a long long or try to optimise your computations if possible.
At last, an alternative is to search for big integer libraries.
You are using signed integers to compute and a signed integer overflow is undefined behaviour. So whatever your code returns it correct according to the C standard. What usually happens is that you simply get the lower bits of the right result. Which, since it's signed int, can be negative.
If you only want to get an approximate result for large numbers then why not change your code to use double? For small numbers like 3! you would still get 6 but past 17 or so you get something like 4.643+E8, meaning 4.643 * 10^8. The double type will eventually run out of exponents but it gets you a lot further than even unsigned long long.
For capable maximum factorial, you can use unsigned long long for return type of this function. And your function is recursive style, the running time is slower then non-recursive style.
I think here is a good solution
unsigned long long ft_iterative_factorial(int nb)
{
unsigned long long result = 1;
for (int i = 2; i <= nb; i++)
{
result = result * (unsigned long long)i;
}
return result;
}
int main()
{
cout << ft_iterative_factorial(17) << endl;
return 0;
}

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;
}

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;
}

find all Carmichael numbers in a given interval [a,b) - C

I am working in a math software with different features one of them to be to find all Carmichael numbers in a given interval [a,b)
This is my code, but I don't know if I have done it correctly or not cause I can't test it since the smallest Carmichael number is 560 which is too big for my pc to process.
#include <stdio.h>
int main() {
unsigned int begin, end;
printf("Write an int (begin):\n");
scanf("%d", &begin);
printf("Write an int (end):\n");
scanf("%d", &end);
int i;
for( int i=begin; i<end; i++ ) {
long unsigned int a_nr = i-1;
int a[a_nr];
for( int j=0; j<a_nr; j++ ) {
a[j] = j;
}
unsigned long c_nr[a_nr];
for( int k=0; k<a_nr; k++ ) {
unsigned long current_c_nr;
int mod;
for( int l=0; l<i; l++ ) {
current_c_nr= current_c_nr * a[k];
}
mod = current_c_nr%i;
if( mod==a[k] && mod!=a[k] ) {
c_nr[k] = i;
}
}
}
return 0;
}
If it is not correct, where is the mistake?
Thank you
P.S Overflow should be prevented.
When you say "This is my code, but I don't know if I have done it correctly or not cause I can't test it since the smallest Carmichael number is 560 which is too big for my pc to process" then the conclusion is -- you haven't done it correctly. You should be able to process 561 (560 must be a typo) in a small fraction of a second. Even if your algorithm is in principle correct, if it can't handle the smallest Carmichael number then it is useless.
n is Carmichael if and only if it is composite and, for all a with 1 < a < n which are relatively prime to n, the congruence a^(n-1) = 1 (mod n) holds. To use this definition directly, you need:
1) An efficient way to test if a and n are relatively prime
2) An efficient way to compute a^(n-1) (mod n)
For the first -- use the Euclidean algorithm for greatest common divisors. It is most efficiently computed in a loop, but can also be defined via the simple recurrence gcd(a,b) = gcd(b,a%b) with basis gcd(a,0) = a. In C this is just:
unsigned int gcd(unsigned int a, unsigned int b){
return b == 0? a : gcd(b, a%b);
}
For the second point -- almost the worst possible thing you can do when computing a^k (mod n) is to first compute a^k via repeated multiplication and to then mod the result by n. Instead -- use exponentiation by squaring, taking the remainder (mod n) at intermediate stages. It is a divide-and-conquer algorithm based on the observation that e.g. a^10 = (a^5)^2 and a^11 = (a^5)^2 * a. A simple C implementation is:
unsigned int modexp(unsigned int a, unsigned int p, unsigned int n){
unsigned long long b;
switch(p){
case 0:
return 1;
case 1:
return a%n;
default:
b = modexp(a,p/2,n);
b = (b*b) % n;
if(p%2 == 1) b = (b*a) % n;
return b;
}
}
Note the use of unsigned long long to guard against overflow in the calculation of b*b.
To test if n is Carmichael, you might as well first test if n is even and return 0 in that case. Otherwise, step through numbers, a, in the range 2 to n-1. First check if gcd(a,n) == 1 Note that if n is composite then you must have at least one a before you reach the square root of n with gcd(a,n) > 1). Keep a Boolean flag which keeps track of whether or not such an a has been encountered and if you exceed the square root without finding such an a, return 0. For those a with gcd(a,n) == 1, compute the modular exponentiation a^(n-1) (mod n). If this is ever different from 1, return 0. If your loop finishes checking all a below n without returning 0, then the number is Carmichael, so return 1. An implementation is:
int is_carmichael(unsigned int n){
int a,s;
int factor_found = 0;
if (n%2 == 0) return 0;
//else:
s = sqrt(n);
a = 2;
while(a < n){
if(a > s && !factor_found){
return 0;
}
if(gcd(a,n) > 1){
factor_found = 1;
}
else{
if(modexp(a,n-1,n) != 1){
return 0;
}
}
a++;
}
return 1; //anything that survives to here is a carmichael
}
A simple driver program:
int main(void){
unsigned int n;
for(n = 2; n < 100000; n ++){
if(is_carmichael(n)) printf("%u\n",n);
}
return 0;
}
output:
C:\Programs>gcc carmichael.c
C:\Programs>a
561
1105
1729
2465
2821
6601
8911
10585
15841
29341
41041
46657
52633
62745
63973
75361
This only takes about 2 seconds to run and matches the initial part of this list.
This is probably a somewhat practical method for checking if numbers up to a million or so are Carmichael numbers. For larger numbers, you should probably get yourself a good factoring algorithm and use Korseldt's criterion as described in the Wikipedia entry on Carmichael numbers.

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

/***********************************************************************************************************************************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?

Resources