0

I am having trouble on some test cases on the "Equations" challenge on hackerrank.com. This is where the problem is stated: https://www.hackerrank.com/challenges/equations.
I'm pretty sure I understand the logic, but there is still a bug in my program (or a flaw in my logic).

public class Solution
{
    public static void mark(boolean[] a, int i, int n) //sieve util
    {
        int num = i*2;
        while(num <= n)        
        {
            a[num] = true;
            num += i;
        }
    }
    public static long legendre(int n, int p) //get prime power   
    {
        long ans = 0;
        int k = p;
        while(n/k != 0)        
        {
            ans += (long)n/k;
            k *= p;
        }
        return ans;
    }
    public static void main(String[] args)
    {
       long mod = 1000007; 
       int n;
       Scanner input = new Scanner(System.in);
       n = input.nextInt();
       boolean[] a = new boolean[n+1];
       for(int i = 2; i <= n; ++i) //sieve
       {
           if(a[i] == false)
           {
               mark(a,i,n);
           }
       }      
       boolean isEven = true;
       long ans = 1, power = 1;
       for(int i = 2; i <= n; ++i)
       {
           if(a[i] == false)
           {
               power = legendre(n,i);
               if(power%2 == 1)
               {
                   isEven = false;
               }
               ans *= (2*power+1);
               ans %= mod;
           }
       }
       if(isEven == true) //symmetric solution
            ans -= 1;
       if(n == 1) //special case
            System.out.println(1);
       else
            System.out.println(ans);                  
    }
}

What I attempted to do: create a table of prime values and then get the power of each prime factor of n!. I used this formula: http://www.cut-the-knot.org/blue/LegendresTheorem.shtml. My program produced the correct output for n = 105387 (which is 629416), but for n = 131399, my output is 598995 (should be 856428).

This question has also been asked before here: Sample testcase for Interviewstreet: Equations Someone asked "what is the output for N=131399, I am getting 598995, but it's giving wrong. – peeyush May 26 '12 at 20:33" Apparently my particular bug is not unique.

Community
  • 1
  • 1
user2959071
  • 149
  • 2
  • 9
  • 1
    Are you getting an overflow possibly? If you change your ints (the ones that may become large) to longs do you still see similar results? – takendarkk Sep 07 '14 at 05:21
  • 1
    Wow. I honestly can not believe that worked. I've done so many math programming challenges and I'm constantly thinking about overflow, but I really thought I was safe here. Thanks for bearing with me – user2959071 Sep 07 '14 at 05:30
  • 1
    No problem. I'm glad it was really that simple, I don't have the brainpower for much more than that atm. – takendarkk Sep 07 '14 at 05:31

2 Answers2

1

When calling legendre(131399,46349), variable k overflows.

Change the type of this variable from int to long.


BTW, you could have easily tracked it by adding an assertion inside the loop:

if (k < 0)
    System.out.println(k);
barak manos
  • 29,648
  • 10
  • 62
  • 114
0

Changing to long won't work, I just tried. You need to use BigInteger.

Check out my solution...

public class Solutions {

    static boolean isPrime(int p) {
        boolean num = false;
        if (p == 2 || p == 3) {
            return true;
        }
        for (int j = 2; j <= Math.sqrt(p); j++) {
            if (p % j == 0) {
                num = false;
                break;
            } else {
                num = true;
            }
        }
        return num;
    }

    public static void main(String[] args) {
        long mod = 1000007;
        int n;
        Scanner input = new Scanner(System.in);
        n = input.nextInt();
        BigInteger bresult = BigInteger.ONE;
        long x = n;
        for (int i = 2; i <= x; i++) {
            if (isPrime(i)) {
                int k = 1;
                long power = 0;
                while ((Math.pow(i, k) <= x)) {

                    power += n / Math.pow(i, k);

                    k++;
                }
                bresult = bresult.multiply(BigInteger.valueOf(power * 2 + 1));
            }

        }
        System.out.println(bresult.mod(BigInteger.valueOf(mod)));

    }
}
CSchulz
  • 10,882
  • 11
  • 60
  • 114