What this code is basically supposed to do is find how many even divisors a number has.
For example the number 100
has the divisors 1, 2, 4, 5, 10, 20, 25, 50, 100
of which 6 (2, 4, 10, 20, 50
and 100
) are even. So we output 6.
The first line of input is supposed to be the number of test cases (t
). And for each of the following t
numbers, we have to calculate the number of even divisors.
import java.math.*;
import java.io.*;
import java.util.*;
public class DivisorPrint {
public static final Scanner sc = new Scanner(System.in);
public static List<Integer> primes = new ArrayList<>();
public static Map<Integer, Integer> factorsOccur = new HashMap<>();
public static List<Integer> factors = new ArrayList<>();
public static void main(String... arrgs){
int t = sc.nextInt(), i;
for (i =0; i < t; i++) {
int n = sc.nextInt(), temp;
int k = 0, l = 0;
fillPrimes(n);
int curr = primes.get(k);
if (n %2 != 0) {
System.out.println(0);
} else {
// checking if curr is factor
while(curr <= n) {
temp = n;
while (temp != 0) {
if (temp %curr == 0) {
l++;
temp /= curr;
} else
break;
}
if (l!=0) {
factorsOccur.put(curr, l);
factors.add(curr);
}
k++;
l=0;
if (k >= primes.size())
break;
else
curr = primes.get(k);
}
// now we have the list of primes
Collections.sort(factors);
if (n == 2) {
System.out.println(1);
} else {
int occurTwo = factorsOccur.get(factors.get(0));
int total = 0;
if (factors.size() ==1) {
total = occurTwo;
} else {
total = 1;
for (int r = 1; r < factors.size(); r++) {
total *= (factorsOccur.get(factors.get(r)) + 1);
}
total *= occurTwo;
}
System.out.println(total);
}
}
factorsOccur.clear();
factors.clear();
}
}
public static void fillPrimes(int n) {
int f = primes.size();
if (f == 0) {
// there are no primes
primes.add(2);
f++;
}
// get all prime numbers up to the value of n
if (primes.get(f-1) <= n) {
int check = 0;
if (primes.get(f-1) == 2) {
check = 3;
} else {
check = primes.get(f-1) + 2;
}
boolean isPrime = true;
while (check <= n) {
for (int i = 0; primes.get(i)*primes.get(i) <= check; i++) {
if (check % primes.get(i) == 0) {
isPrime = false;
break;
}
}
if (isPrime)
primes.add(check);
isPrime = true;
check += 2;
}
}
}
}
I don't know how to calculate the time complexity for the code above. But it runs slower than this approach:
- checking if each number (from 1 to square root of
n
) - divides n and then if that number is even, and then increment the counter.
- Then we check if the number n/i divides n and then increment the counter once more if it does.
Shouldn't this code run faster than that? Especially for a large number of test cases.
import java.math.*;
import java.io.*;
import java.util.*;
public class Solution {
public static final Scanner sc = new Scanner(System.in);
public static void main(String... arrgs) {
int t = sc.nextInt(), n, total, opp;
for (int i = 0; i < t; i++) {
n = sc.nextInt();
total = 0;
if (n%2 !=0)
System.out.println(0);
else {
for (int j = 2; j*j <= n; j++) {
if (j*j == n) {
total++;
} else {
if (n%j == 0) {
if (j%2 ==0)
total++;
opp = n/j;
if (n %opp == 0 && opp%2 ==0) {
total++;
}
}
}
}
total++;
System.out.println(total);
}
}
}
}
How can I improve the DivisorPrint class so it runs faster than the Solution.
j
is a multiple of2
instead of just usingj += 2
? \$\endgroup\$n
? And if I increment by2
, take100
as an example. Factors are1
,2
,4
,5
,10
,20
,25
,50
, and100
, we are only interested in2
,4
,10
,20
,50
,100
. the loop only goes to the square root ofn
if I increment by2
, I miss out on5
, and it's pair20
, because5 * 20 = 100
\$\endgroup\$