Divisible Problem on Hackerearth Partially Accepted - c

I completed a challenge in HackerEarth using C but the solution is only partially accepted. I tried to change the data type also but no success.
Question is:
You are given an array A of size N that contains integers. Here, N is an even number. You are required to perform the following operations:
Divide the array of numbers in two equal halves
Note: Here, two equal parts of a test case are created by dividing the array into two equal parts.
Take the first digit of the numbers that are available in the first half of the array (first 50% of the test case)
Take the last digit of the numbers that are available in the second half of the array (second 50% of the test case)
Generate a number by using the digits that have been selected in the above steps
Your task is to determine whether the newly-generated number is divisible by 11.
My solution is:
#include <stdio.h>
#include <math.h>
int main(){
int N;
scanf("%d",&N);
int A[N];
for(int i = 0;i < N;i++)
scanf("%d",&A[i]);
long int sum = 0;
for(int i = 0;i < N/2;i++){
int digits =(int)log10(A[i]);
int first_digit = (int)(A[i] / pow(10,digits));
sum = (sum*10) + first_digit;
}
for(int i = N/2;i < N;i++){
int last_digit = A[i] % 10;
sum = (sum*10)+last_digit;
}
sum % 11 == 0? printf("OUI"):printf("NON");
return 0;
}

The problem says that N will be upto 100,000.
Dealing with such many digits, the calculation of sum will cause overflow.
You should divide sum by 11 and take modulo after each update of sum.

You shouldn't use floating-point numbers or built-in integer types for this kind of problems, because their precisions wouldn't be enough. An integer number is divisible by 11 if the alternating sum of its decimal digits is divisible by 11. So a simple solution would be:
#include <stdio.h>
#include <string.h>
int main (void)
{
int sum = 0, sign = 1;
int n, i;
scanf("%d", &n);
for (i = 0; i < n; ++i) {
char num[100];
scanf("%s", num);
sum += sign * (num[i < n / 2 ? 0 : strlen(num) - 1] - '0');
sign = -sign;
}
puts(sum % 11 == 0 ? "OUI" : "NON");
return 0;
}
Note: Error checking and input validation is omitted for brevity.

100 pecent accepted hackerearth Divisible problem:
#include<stdio.h>
int main() {
long int N;
scanf("%ld", &N);
long int a[N];
int m = 0, n = 0, i;
for (i = 0; i < N; i++)
scanf("%ld", &a[i]);
for (i = 0; i < N / 2; i++) {
if (a[i] >= 100000)
a[i] = a[i] / 100000;
else if (a[i] >= 10000)
a[i] = a[i] / 10000;
else if (a[i] >= 1000)
a[i] = a[i] / 1000;
else if (a[i] >= 100)
a[i] = a[i] / 100;
else if (a[i] >= 10)
a[i] = a[i] / 10;
else
a[i] = a[i];
if (i % 2 == 0)
m += a[i];
else
n += a[i];
}
for (i = N / 2; i < N; i++) {
if (i % 2 == 0)
m += (a[i] % 10);
else
n += (a[i] % 10);
}
if ((abs(m - n)) == 0 || ((abs(m - n)) % 11) == 0)
printf("OUI");
else
printf("NON");
}

function divisibilty(n, arr) {
return arr[n - 1] % 10 == 0 ? "Yes" : "No";
}
console.log(divisibilty(5, [185, 125, 165, 211, 814])); // No
console.log(divisibilty(2, [98, 70])); // Yes

Related

How to fix 'time limit exceeded' in some test cases when using the for loop?

We have a series of numbers which is the sum of numbers from 1 to n.(1,3,6,10,...)
The question wants me to find the smallest number in this series which has k divisors.
My code works properly on all test cases but it exceeds the time limits.
It has one while loop and one for loop inside it.
int main()
{
int k, sum, counter = 0, n = 1;
scanf("%d", &k);
while (counter != k) {
counter = 0;
sum = n*(n + 1) / 2; //sum of numbers from 1 to n.(formula)
for (int i = 1; i <= sum / 2; i++) //counts the divisors
if (sum%i == 0)counter++;
counter++; //adds one to the counter because of number 1
n++;
}
printf("%d",sum);
return 0;
}
And here is a example:
Input:k=4
Output:6
What should I do to have a faster and better program?
Did not find a good dup. Here is a solution with O(sqrt(n)) complexity. It's taken from https://www.geeksforgeeks.org/count-divisors-n-on13/
// function to count the divisors
int countDivisors(int n)
{
int cnt = 0;
for (int i = 1; i <= sqrt(n); i++) {
if (n % i == 0) {
// If divisors are equal,
// count only one
if (n / i == i)
cnt++;
else // Otherwise count both
cnt = cnt + 2;
}
}
return cnt;
}
On the same site, there is one that runs in O(n^(1/3)) that is slightly more complex. It's for C++, but just add #include <stdbool.h> and it should work.
void SieveOfEratosthenes(int n, bool prime[],
bool primesquare[], int a[])
{
// Create a boolean array "prime[0..n]" and initialize all entries as
// true. A value in prime[i] will finally be false if i is Not a prime,
// else true.
for (int i = 2; i <= n; i++)
prime[i] = true;
// Create a boolean array "primesquare[0..n*n+1]" and initialize all
// entries it as false. A value in squareprime[i] will finally be true
// if i is square of prime, else false.
for (int i = 0; i <= (n * n + 1); i++)
primesquare[i] = false;
// 1 is not a prime number (Look it up if you doubt it)
prime[1] = false;
for (int p = 2; p * p <= n; p++) {
// If prime[p] is not changed, then it is a prime
if (prime[p] == true) {
// Update all multiples of p
for (int i = p * 2; i <= n; i += p)
prime[i] = false;
}
}
int j = 0;
for (int p = 2; p <= n; p++) {
if (prime[p]) {
// Storing primes in an array
a[j] = p;
// Update value in primesquare[p*p], if p is prime.
primesquare[p * p] = true;
j++;
}
}
}
// Function to count divisors
int countDivisors(int n)
{
// If number is 1, then it will have only 1
// as a factor. So, total factors will be 1.
if (n == 1)
return 1;
bool prime[n + 1], primesquare[n * n + 1];
int a[n]; // for storing primes upto n
// Calling SieveOfEratosthenes to store prime factors of n and to store
// square of prime factors of n
SieveOfEratosthenes(n, prime, primesquare, a);
// ans will contain total number of distinct divisors
int ans = 1;
// Loop for counting factors of n
for (int i = 0;; i++) {
// a[i] is not less than cube root n
if (a[i] * a[i] * a[i] > n)
break;
// Calculating power of a[i] in n.
int cnt = 1; // cnt is power of prime a[i] in n.
while (n % a[i] == 0) // if a[i] is a factor of n
{
n = n / a[i];
cnt = cnt + 1; // incrementing power
}
// Calculating number of divisors. If n = a^p * b^q then total
// divisors of n are (p+1)*(q+1)
ans = ans * cnt;
}
// if a[i] is greater than cube root of n
// First case
if (prime[n])
ans = ans * 2;
// Second case
else if (primesquare[n])
ans = ans * 3;
// Third casse
else if (n != 1)
ans = ans * 4;
return ans; // Total divisors
}
If the above is not enough, you should look into some kind of dynamic programming. Both of the above method is calculating each number from scratch. But if you're going to do it for several numbers, it is quite possible that you can use information from previous numbers. Just to give an idea for how it works, here is an algorithm calculating all primes from 2 to n:
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
// After running this function, prime[n] will be true iff n is a prime
void createPrimeArray(bool *prime, size_t size)
{
prime[0] = prime[1] = false;
for(size_t i=2; i<size; i++)
prime[i] = true;
for(size_t i=2; i<sqrt(size); i++) {
size_t j=i;
while(!prime[j])
j++;
for(size_t k=2*j; k<size; k+=j)
prime[k] = false;
}
}
int main(void)
{
bool prime[200];
createPrimeArray(prime, 200);
for(int i=0; i<200; i++) {
if(prime[i])
printf("%d ", i);
}
}
The above can possibly be optimized further. It's purpose is to show how you can reuse information. After the first run in the second for loop in createPrimeArray we have marked all numbers that are dividable by 2 as non-primes, and thus we don't have to care about those anymore.

Is it the efficeint program to rotate array in left direction?

#include<stdio.h>
#include<stdlib.h>
main()
{
int i,j,l,m,n;
j=0;
printf("\nenter 5 element single dimension array\n");
printf("enter shift rate\n");
scanf("%d",&n);
/* Here we take input from user that by what times user wants to rotate the array in left. */
int arr[5],arrb[n];
for(i=0;i<=4;i++){
scanf("%d",&arr[i]);
}
/* Here we have taken another array. */
for(i=0;i<=4;i++){
printf("%d",arr[i]);
}
for(i=0;i<n;i++){
arrb[j]=arr[i];
j++;
// These loop will shift array element to left by position which's entered by user.
}
printf("\n");
for(i=0;i<=3;i++){
arr[i]=arr[i+n];
}
for(i=0;i<=4;i++){
if(n==1 && i==4)
break;
if(n==2 && i==3)
break;
if(n==3 && i==2)
break;
printf("%d",arr[i]);
}
//To combine these two arrays. Make it look like single array instead of two
for(i=0;i<n;i++){
printf("%d",arrb[i]);
}
// Final sorted array will get printed here
}
Is it the efficeint program to rotate array in left direction?
Actually, very complicated, and some problems contained:
for(i = 0; i < n; i++)
{
arrb[j] = arr[i];
j++;
}
Why not simply:
for(i = 0; i < n; i++)
{
arrb[i] = arr[i];
}
There is no need for a second variable. Still, if n is greater than five, you get into trouble, as you will access arr out of its bounts (undefined behaviour!). At least, you should check the user input!
for(i = 0; i <=3 ; i++)
{
arr[i] = arr[i + n];
}
Same problem: last accessible index is 4 (four), so n must not exceed 1, or you again access the array out of bounds...
Those many 'if's within the printing loop for the first array cannot be efficient...
You can have it much, much simpler:
int arr[5], arrb[5];
// ^
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(i + n) % 5];
This does not cover negative values of n, though.
arrb[i] = arr[(((i + n) % 5) + 5) % 5];
would be safe even for negative values... All you need now for the output is:
for(int i = 0; i < 5; ++i)
printf("%d ", arrb[i]);
There would be one last point uncovered, though: if user enters for n a value greater than INT_MAX - 4, you get a signed integer overflow, which again is undefined behaviour!
We can again cover this by changing the index formula:
arrb[i] = arr[(5 + i + (n % 5)) % 5];
n % 5 is invariant, so we can move it out of the loop:
n %= 5;
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(5 + i + n) % 5];
Finally, if we make n positive already outside, we can spare the addition in the for loop.
n = ((n % 5) + 5) % 5;
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(i + n) % 5]; // my original formula again...
Last step is especially worth considering for very long running loops.
I think you want to do something like this (you should check that 0 <= n <= 5, too):
int b[5];
int k = 0;
for(i=0; i<5; i++){
if (i < 5 - n)
b[i] = arr[i+n];
else
{
b[i] = arr[k];
k++;
}
}
Array b is used to save the rotated matrix.

I'm using the sieve of Eratosthenes as a primality test. Why am I getting that 2297 is composite?

I am using the Sieve of Eratosthenes to calculate the first 500 prime numbers. What the program does is evauate n % p where n is the user input and p is between 2 and sqrt(n).
I'm testing my program for the case n = 2297, which is a prime. Why does my program say it's composite?
bool primalityTestSieve(int n){
if(n == 2) return true; //tiny complication due to ceil(sqrt(2))
//Sieve with first MAX
bool arr[MAX - 1];
int i, j, s = ceil(sqrt(n));
for(i = 2; i < MAX; i++){
arr[i - 2] = true; //fill arr[] with true
}
for(i = 2; i < (int) sqrt(MAX); i++){
if(arr[i - 2]){
for(j = i*i; j < MAX; j+= i)
arr[j - 2] = false;
}
}
//Array storing the primes
int primes[MAX];
j = 0; //Counter for the index of the primes
for(i = 0; i < MAX; i++)
if(arr[i]){
primes[j] = i + 2;
j++;
}
//Prime test, first using sieve
for(i = 0; primes[i] <= s; i++)
if(n % primes[i] == 0) return false;
//Naive prime test for larger divisors
for (i = primes[j]; i <= s/2; i++)
if(((n % 2) == 0)||((n % (2*i + 1)) == 0)) return false;
return true;
}
Note that MAX is a parameterised macro and is equal to 500.
Your code uses the sieve to find the primes between 2 and 500. (Not the first 500 primes as you seem to say in your text).
Then you copy those primes into the primes[] array with j as the count of how many items are in the array. So at this point primes[] contains some numbers less than 500 followed by a bunch of junk.
Then you have the code:
for(i = 0; primes[i] <= s; i++)
s would be 48 for n == 2297. This loop will then check for n being divisible by any of the primes up to 48 , which would fail. (This loop should also have i < j as a condition so it does not read into the junk if you enter a large n).
However you then write:
for (i = primes[j]; i <= s/2; i++)
Remmeber that j currently holds the prime count, and the primes are in primes[0] through primes[j-1]. This means primes[j] is a junk value; so you set i to junk causing undefined behaviour.
(I'm not sure what you were actually trying to do in that last loop, it's unclear where you want to start and finish, or why you test n%2 every loop iteration, etc. - if you can describe what you are trying to do there then I'll suggest some code).

Calculating large power of a number in c

I am writing a program in c to store 2^100000, and I am using arrays to store the result.
Here is the full code:
#include <stdio.h>
#include <math.h>
int main()
{
int test, n, i, j, x, resul;
int a[200], m, temp;
scanf("%d", &test);
for (i = 0; i < test; i++) {
a[0] = 3; // initializes array with only 1 digit, the digit 1.
m = 1; // initializes digit counter
scanf("%d", &n);
temp = 0; // Initializes carry variable to 0.
for (i = 1; i < n; i++) {
for (j = 0; j < m; j++) {
x = a[j] * 2 + temp; //x contains the digit by digit product
a[j] = x % 10; //Contains the digit to store in position j
temp = x / 10; //Contains the carry value that will be stored on later indexes
}
while (temp > 0) { //while loop that will store the carry value on array.
a[m] = temp % 10;
temp = temp / 10;
m++; // increments digit counter
}
}
for (i = m - 1; i >= 0; i--) //printing answer
printf("%d", a[i]);
}
return 0;
}
Can some one tell me a more efficient way to do so to reduce the time complexity?
2^n in binary is an (n+1)-digit integer with every bit set to 0 except the most significant bit being set to 1. e.g: 32 = 2^5 = 0b100000
Likewise, 2^100000 can be computed by setting the 100001-th bit in a zeroed 100001 bit long integer to 1. O(1) is as time efficient as you can go.
There are several problems with your code:
The array a is defined with a size of only 200 digits. This is much too small for 2^100000 that has 30103 digits. You should increase the array size and check for overflow in the multiplication algorithm.
You initialize a[0] = 3; and comment this as the digit 1. Indeed you should write a[0] = 1;.
The second loop for (i = 1; i < n; i++) should include the desired power number: you should write for (i = 1; i <= n; i++).
You use the same loop variable for the outer loop and the second level ones, causing incorrect behavior.
You do not test the return value of scanf, causing undefined behavior on invalid input.
You do not check for overflow, invoking undefined behavior on large values.
Here is a corrected version:
#include <stdio.h>
int main()
{
int n, i, j, x, m, test, temp;
int a[32000];
if (scanf("%d", &test) != 1)
return 1;
while (test-- > 0) {
if (scanf("%d", &n) != 1)
break;
a[0] = 1; // initializes array with only 1 digit, the number 1.
m = 1; // initializes digit counter
temp = 0; // Initializes carry variable to 0.
for (i = 1; i <= n; i++) {
for (j = 0; j < m; j++) {
x = a[j] * 2 + temp; //x contains the digit by digit product
a[j] = x % 10; //Contains the digit to store in position j
temp = x / 10; //Contains the carry value that will be stored on later indexes
}
// while loop that will store the carry value on array.
if (temp > 0) {
if (m >= (int)(sizeof(a)/sizeof(*a)))
break;
a[m++] = temp;
temp = 0;
}
}
if (temp > 0) {
printf("overflow");
} else {
for (i = m - 1; i >= 0; i--) //printing answer
putchar('0' + a[i]);
}
printf("\n");
}
return 0;
}
Running this code with input 1 and 100000 on my laptop takes about 6,5 seconds. That's indeed quite inefficient. Using a few optimization techniques that do not really change the complexity of this simple iterative algorithm still can yield a dramatic performance boost, possibly 100 times faster.
Here are some ideas:
store 9 digits per int in the array instead of just 1.
multiply by 2^29 in each iteration instead of just 2, using long long to compute the intermediary result. Initialize the first step to 1 << (n % 29) to account for n not being a multiple of 29. 2^29 is the largest power of 2 less than 10^9.
Here is version that implements these two ideas:
#include <stdio.h>
int main() {
int n, i, j, m, test, temp;
int a[32000];
if (scanf("%d", &test) != 1)
return 1;
while (test-- > 0) {
if (scanf("%d", &n) != 1)
break;
i = n % 29;
n /= 29;
a[0] = 1 << i;
m = 1;
temp = 0;
for (i = 1; i <= n; i++) {
for (j = 0; j < m; j++) {
long long x = a[j] * (1LL << 29) + temp;
a[j] = x % 1000000000;
temp = x / 1000000000;
}
if (temp > 0) {
if (m >= (int)(sizeof(a)/sizeof(*a)))
break;
a[m++] = temp;
temp = 0;
}
}
if (temp > 0) {
printf("overflow");
} else {
printf("%d", a[m - 1]);
for (i = m - 2; i >= 0; i--)
printf("%09d", a[i]);
}
printf("\n");
}
return 0;
}
Running it on the same laptop computes the correct result in only 33ms, that's 200 times faster.
The Time Complexity is the same, but implementation is much more efficient.
Be aware that native C integers are limited, in practice to some power of two related to the word size of your computer (e.g. typically 32 or 64 bits). Read about <stdint.h> and int32_t & int64_t.
Maybe you want some bignums (or bigints), a.k.a. arbitrary precision arithmetic.
The underlying algorithms are very clever (and more efficient than the naive ones you learned in school). So don't try to reinvent them, and use a library like GMPlib

Counting Positive Integers with a Given Number of Divisors

basically what i was trying to do is insert an integer k that represents the number of divisors and then finding all the numbers that have k divisors from 1-100000
#include <stdio.h>
int main(void)
{
int k, x = 1, y = 100000, divisor, count;
printf("Enter the target number of divisors:\n");
scanf("%d", &k);
for (divisor = 0; divisor <= 1; divisor++)
if (x % divisor == 0 && y % divisor == 0)
count++;
printf("There are %d numbers between 1 and 100000 inclusive which have exactly %d divisors\n", k, divisor);
return 0;
}
However I can't seem to be able to do it, please do help me as I'm fairly new to the programming scene and haven't found an answer elsewhere.
There is a theorem that states if you have the canonical representation of an integer being a1b1 * a2b2 ... anbn then the number of divisors of this integer is (b1 + 1) * (b2 + 1) ... (bn + 1).
Now that you have this theorem, you can modify slightly Eratosthenes's sieve to get all integers up to 100 000 in canonical form.
Here is some code that does what I mean by modified erathosthenes's sieve.
const int size = 100000;
int devs[size + 1];
void compute_devs() {
for (int i = 0; i < size + 1; ++i) {
devs[i] = (i%2 == 0) ? 2 : 1;
}
int o = sqrt(size);
for (int i = 3; i <= size; i += 2) {
if (devs[i] != 1) {
continue;
}
devs[i] = i;
if (i <= o) {
for (int j = i * i; j < size; j += 2 * i) {
devs[j] = i;
}
}
}
}
After calling compute_devs the value of devs will store the value of the greatest prime divisor of each number up to size. I will leave the rest of the task to you, but having this array it becomes pretty straight forward.

Resources