0

I wrote this code to find last digit of a exponent b but SPOJ says its wrong. I tried almost all test cases but couldn't find the error. Problem:http://www.spoj.com/problems/LASTDIG/ My Solution:

package spoj;

import java.util.Scanner;

public class LastDigit {

    public static void main(String[] args) throws java.lang.Exception {
        Scanner p = new Scanner(System.in);
        for(int test = p.nextInt();test>0;test-- ){
            int a = p.nextInt();
            int b = p.nextInt();
            int result = (int) Math.pow(a,b);
            System.out.println(result%10);
        }
    }
}
Hexaholic
  • 3,299
  • 7
  • 30
  • 39
Aman
  • 115
  • 1
  • 10

8 Answers8

3

Math.powis a floating point operation! It doesn't compute the exact result. That's why you have that funny cast to int in there.

Therefore you need to use BigInteger or write your own exponentiation function. The latter is the more desirable since the way more efficient way to compute the last digit is to reduce a modulo 10, b modulo 4, then take the power and then reduce modulo 10 again. This should even work within the range were floating-point arithmetic is exact.

Also: You really should have a check in there whether a % 10is even invertible modulo 10 if bis negative. Otherwise your doing the modulo-10-equivalent of a division by zero.

Johannes Hahn
  • 363
  • 3
  • 18
2

I'm gonna suggest some weird approach that is gonna work with this problem, as a kind of 'fun fact', not the solution that should be used (at least I don't think it should be).

Your a is 0 < a <= 20, so look at those 20 numbers.

For example take 6 and look at the results: 6, 36, 216, 1296, 7776.... See? Everything ends in 6, so that's easy here.

Harder one: 19. Results: 19, 361, 6859, 130321, 2476099.... See a pattern? 9, 1, 9, 1....

Another one just to demonstrate: 8, 64, 512, 4096, 32768, 262144..., so pattern is 8, 4, 2, 6.

Basically for every number there is a pattern for last digits, you just need to take the right modulo from exponent and result is in O(1).

Math people - please don't eat me alive.

Shadov
  • 5,421
  • 2
  • 19
  • 38
  • 1
    Well, if you write software around such assumptions, you either have to try *all* values (not appropriate for this value range) or prove formally that this approach is correct, i.e. that this pattern is not just coincidence for the small numbers you looked at. Anyway, you got my+1 for pointing into the right direction. – Holger Oct 18 '16 at 10:04
  • That's why I wrote the 'fun fact' part, that assumption about a pattern should definitely be proven first. – Shadov Oct 18 '16 at 10:05
  • 1
    That’s more than a “fun fact”, I’m very confident that finding this or a similar approach is what this task was about, as calculating, e.g. the complete result of 20²¹⁴⁷⁴⁸³⁰⁰⁰ doesn’t sound like an option… – Holger Oct 18 '16 at 10:07
  • 3
    As one of those "math people" ;-) I'm telling you that this isn't weird in any way. Instead: This is the exact right approach to the problem. You find that every pattern is of length 1,2 or 4 so that one really only needs to know a%10 and b%4 to compute the power. – Johannes Hahn Oct 18 '16 at 10:08
  • 1
    @JohannesHahn Exactly. And it's a very easy thing to prove. Using this method, you can calculate the last digit of any power in linear time (if the size of the input is the number of digits in `a` and `b`.) – biziclop Oct 18 '16 at 10:18
1

Math.pow works with floating point numbers with all the rounding errors that includes. The last digit for even moderately large a and b will thus be wrong.

As I was reminded in the comments by David Wallace, the more immediate error is to try to fit a 54+1bit signed integer, which is the integer range that is provided using a double mantissa, into a 31+1bit signed integer. The error due to overflow occurs for numbers smaller than those where rounding errors start. One can avoid this by employing the long (int) data type.

For a proper solution you will need to use modular exponentiation, or find the period of the last digit of powers of a (or a%10).

Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • I don't believe there are any values of `Math.pow(a,b)` that fit in an `int`, but are wrong (where `a` and `b` are `int`). Can you exhibit any, to support your answer? – Dawood ibn Kareem Oct 18 '16 at 09:51
  • 1
    @David Wallace: who says that the result fits into an `int`? – Holger Oct 18 '16 at 09:53
  • @Holger, this answer implies that this is a rounding/accuracy problem. It's not. The problem is that OP is trying to put _enormous_ numbers into an `int`. So the whole "rounding error" bit is completely irrelevant. – Dawood ibn Kareem Oct 18 '16 at 09:54
  • 1
    @David Wallace: well, it’s *both*. The result might not fit into an `int` *and* exceed the precision of `double`. Since the cast to `int` isn’t actually necessary, as `%` works on `double` as well, it’s worth mentioning that removing the obsolete conversion to `int` alone won’t solve the problem. But yes, the inappropriateness of `int` is missing in this answer. – Holger Oct 18 '16 at 09:59
1

package spoj;

import java.util.Scanner;

public class LastDigit {

public static void main(String[] args) throws java.lang.Exception {
    Scanner p = new Scanner(System.in);
    for(int test = p.nextInt();test>0;test-- ){

        int a = p.nextInt();
        int b = p.nextInt();
        System.out.println(LastDigit(a,b));

    }
}

public static int LastDigit(int a, int b) {
    int k,f=1;
    if(b==0)
        return 1;
    else {
        k =b%4;
        if(k==0)
            b=4;
        else
            b=k;
        for(int i=0;i<b;i++)
            f=f*a;

        return(f%10);
    }
}

}

This approach is working fine. Thanks all :)

Aman
  • 115
  • 1
  • 10
0

The thing is that you only want the last digit, so you don't need to know the final result. . Something with:

int r = (a * a) % 10;
    for (int n = 1; n < b - 1; n++){
        r *= a;
        r = r % 10;
    }

This works. Give me a moment and I'll explain propely . This is correct approach I believe.

[Edit]

Ok, I'm not a mathematician (and not great at explaining) so no proof, but by example:

Wit powers of 4, ( 4 * 4 * 4 * 4 ...) the last digit will be 4 or 6. It doesn't matter if you multiply 16 by 4, or 6 by 4, or even 256 by 4 the last digit will be 4, The point is, you don't need the whole value to keep track of what the last digit is. I don't know how to put it, but think about:

3 * 7 = 21 and

27 * 3 = (60 + 21) = 81.

Sorry. Can explain any better. I think this is solution that OP was expected to find though.

0
    import java.util.Scanner;

    public class LastDigit{

       public static void main(String []args){
        Scanner p = new Scanner(System.in);
        System.out.println("Enter a:");
        int a = p.nextInt();
        System.out.println("Enter b:");
        int b = p.nextInt();
        switch (a%10){
            case 0:case 1:case 5: case 6:
                System.out.println("Last digit is: "+a%10);    //if a ends with 0,1,5 or 6 a^b ends with 0,1,5 or 6 regardless what b is
                 break; 
            case 4:
                if(b%2==1){
                   System.out.println("Last digit is: "+4);     // if a ends with a 4 a^b ends with 4 if b is odd or ends with 6 if b is even                   
                }
               else{
                   System.out.println("Last digit is: "+6);
                }
                 break; 
            case 9:                                             
                if(b%2==1){
                    System.out.println("Last digit is: "+9);    // see case 4
                }
                else{
                   System.out.println("Last digit is: "+1);
                }
                 break; 
            case 2:
                if(b%4==1){                                         // if a ends with 2 a^b ends with 2,4,8 or 6 depending on what b%4 is
                   System.out.println("Last digit is: "+2);
                }
                if(b%4==2){
                    System.out.println("Last digit is: "+4);
                }
                if(b%4==3){
                    System.out.println("Last digit is: "+8);
                }
                else{
                     System.out.println("Last digit is: "+6);
                }
                 break; 
            case 3:
                if(b%4==1){                                         // if a ends wizh 3 a^b ends with 3,9,7 or 1 depending on what b%4 is
                  System.out.println("Last digit is: "+3);
                }
                if(b%4==2){
                  System.out.println("Last digit is: "+9);
                }
                if(b%4==3){
                  System.out.println("Last digit is: "+7);
                }
                else{
                  System.out.println("Last digit is: "+1);
                }
                break; 
            case 7:
                if(b%4==1){
                    System.out.println("Last digit is: "+7);
                }
                if(b%4==2){
                    System.out.println("Last digit is: "+9);
                }
                if(b%4==3){
                    System.out.println("Last digit is: "+3);
                }
                else{
                    System.out.println("Last digit is: "+1);
                }
                 break; 
            case 8: 
                if(b%4==1){
                    System.out.println("Last digit is: "+8);
                 }
                 if(b%4==2){
                    System.out.println("Last digit is: "+4);
                 }
                 if(b%4==3){
                    System.out.println("Last digit is: "+2);
                 }
                 else{
                     System.out.println("Last digit is: "+6);
                }
                 break;                 
        };
       }
    }
Eritrean
  • 15,851
  • 3
  • 22
  • 28
0

Here is a Kotlin function with O(1) Time Complexity. This only calculated the required last digit of the result.

The last digit of any number, having integer power, varies cyclically i.e the last digit repeats itself after certain steps and is fixed for any number.

fun LastDigit(a: Int, b: Int): Int {
    var ld = a%10
    if(ld==0 || ld==1 || ld==5 || ld==6){
        return ld
    }
    if(ld==2 ){
        val n = b%4
        if(n==1)
            return 2
        if(n==2)
            return 4
        if(n==3)
            return 8
        if(n==0)
            return 6

    }
    if( ld==3){
        val n = b%4
        if(n==1)
            return 3
        if(n==2)
            return 9
        if(n==3)
            return 7
        if(n==0)
            return 1

    }
    if(ld ==7 ){
        val n = b%4
        if(n==1)
            return 7
        if(n==2)
            return 9
        if(n==3)
            return 3
        if(n==0)
            return 1

    }
    if(ld ==8 ){
        val n = b%4
        if(n==1)
            return 8
        if(n==2)
            return 4
        if(n==3)
            return 2
        if(n==0)
            return 6
    }

    if(ld==4){
        val n = b%2
        if(n==1)
            return 4
        if(n==0)
            return 6
    }
    if(ld==9){
        val n = b%2
        if(n==1)
            return 9
        if(n==0)
            return 1
    }
    return -1
}
-1

Your code is correct working fine:

Scanner p = new Scanner(System.in);
            for (int test = p.nextInt(); test > 0; test--) {
                int a = p.nextInt();
                int b = p.nextInt();
                int result = (int) Math.pow(a, b);
                System.out.println("Result:"+result);
                 System.out.println("Last Digit:"+result % 10);
            }

Output:

1

2

14

Result:16384

Last Digit:4

Jay Prakash
  • 787
  • 6
  • 22