Last active
February 11, 2025 00:37
-
-
Save Siss3l/84b4dd68a5a7e3746acaa5242877aa50 to your computer and use it in GitHub Desktop.
Returns the last nonzero digits of a factorial
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This code provides functions to find the last nonzero values of a positive factorial. | |
""" | |
def f(n: int, k: int) -> int: | |
""" | |
Returns the k last nonzero digits. | |
.. note:: | |
As f(10**100, 13) is a Googolbang where the 13 last nonzero | |
digits are 5473738735616 with 25*(10**98)-18 trailing zeros. | |
:long_url: https://www.wolframalpha.com/input?i=googol! | |
""" | |
m, l = 10 ** k, [1, 1] | |
for i in range(2, m): | |
if i % 2 == 0 or i % 5 == 0: i = 1 | |
l.append((l[-1] * i) % m) | |
def nf(j: int) -> int: | |
a, b = divmod(j, m) | |
return (pow(l[m - 1], a, m) * l[b]) % m | |
ans, p = 1, 1 | |
while p <= n: | |
q = p | |
while q <= n: | |
ans = (ans * nf(n // q)) % m; q *= 5 | |
p *= 2 | |
def legendre(n: int, p: int) -> int: | |
""" | |
Should be moderate if there are zeros inside the last nonzero digits calculation of Legendre's formula. | |
""" | |
ans = 0 | |
while n: | |
n //= p; ans += n | |
return ans | |
ans *= pow(2, legendre(n, 2) - legendre(n, 5), m) | |
return ans % m | |
if __name__ == "__main__": | |
try: | |
print(f(int(abs(float(__import__("sys").argv[1]))), int(abs(float(__import__("sys").argv[2]))))) | |
except (IndexError, MemoryError, TypeError, ValueError) as e: | |
print(e) |
Comments are disabled for this gist.