Hi, I have the following problem, given a number N between 1 and 1000000, print their last non-zero digit from N!.
The only strategy I've got was try to store the last digits of their fatorial, but this strategy fails when the number N reaches '25'. There's an efficient solution ? since the time limit is strict.
This is my actual strategy, storing in mem[i]
the last digit of i!
:
ll fat = 1, last = 1;
for(int i = 1; i <= 1000010; i++) {
if(i % 5 == 0 || last % 5 == 0) {
ll tmp = last * i;
while(tmp % 10 == 0) tmp /= 10;
last = tmp % 10;
} else {
last = (last * i) % 10;
}
mem[i] = last;
}
Just calculate it without degrees of 2 and 5, because only 2 * 5 gives us 0
+Calculate additional degree of 2
Here
last
is the last digit ofN!
but this multiplicative property with 2 is cumulative ? to find the last digit for a range of numbers, is possible ? being mem[i] the number of the last digit for i! ? sorry for my poor math skills.
you may calc
d2[i]
andlast[i]
just as in my example (starting with copy previous one), after that you may calcmem[i]
I'm memorizing
d2[i]
,mem[i]
. is this way, but it's now slowly, I've tried some optimizations on (*2) degrees but didn't worked.Since N<=1000000 I think it's the easiest way to solve the problem. It just works.
I have a strict time limit, so this solutions get TLE. I think AlexDmitriev solution is the best one, but I'm doubt on how to memorize the last digits take as example his solutions which find each number a time.
O(logN) solution. Calculating n!/(2^max2*5^max5) modulo 2 and modulo 5 (max2 and max5 are degrees of 2 and 5 in n! respectively). After that using chinese remainder theorem to find n!/(2^max2*5^max5) modulo 10. The last step is to print the answer multiplied by 2^(max2-max5). http://pastebin.com/R6uXeWY6
What an amazing solution, thank you, I didn't knew about Chinese remainder theorem.. I didn't got the recursion in 'mod5' function yet, but looks clever, also the 'if' with (n&1) is new to me also, for what it stands about ? again, thank you.
You can read about mod5 here. n&1 checks whether the last bit of n is equal to 1. So it's equivalent to n%2. About bitwise operations you can read more on wiki.