[Python] Short, contest-oriented solution
Multiply all the numbers within the range but only keep track of the # of trailing zeros and the last 10 digits before that. Set the flag if the product ever gr
Multiply all the numbers within the range but only keep track of the # of trailing zeros and the last 10 digits before that. Set the flag if the product ever grows above what `mod` can express. If it does, use the sum of `math.log10()` to calculate the leading 5 digits.\n\nI can probably use the sum of `math.log10()` to estimate whether I need the last 10 digits or just the last 5, but it wouldn\'t be much faster.\n```\nclass Solution:\n    def abbreviateProduct(self, left: int, right: int) -> str:\n        mod = 1\n        zeros = 0\n        div = False\n        for x in range(left, right + 1):\n            mod *= x\n            while not mod % 10:\n                mod //= 10\n                zeros += 1\n            d, mod = divmod(mod, 10000000000)\n            if d:\n                div = True\n        if not div:\n            return f\'{str(mod)}e{zeros}\'\n        else:\n            log_sum = sum(math.log10(i) for i in range(left, right + 1))\n            s = str(10 ** (log_sum % 1))\n            leading = s[0] + s[2:6]\n            return f\'{leading}...{str(mod % 10 ** 5).zfill(5)}e{zeros}\'\n```\n**A note on floating point precision**\nWe only need to get the first 5 leading digits right so we never come close to the limit of floating point precision, but it\'s interesting to note how many leading digits we can get right and by what implementation. The largest exact product `functools.reduce(operator.mul, range(1, 10 ** 6 + 1))` is\n```\n826393168833124006237...\n```\nThe simplest implementation `10 ** (sum(math.log10(i) for i in range(1, 10 ** 6 + 1)) % 1)` gives\n```\n8.263930516641858\n```\n, correct up to 6 digits. `math.fsum()` is more precise than `sum()`: `10 ** (math.fsum(math.log10(i) for i in range(1, 10 ** 6 + 1)) % 1)` gives\n```\n8.263931686266318\n```\n, correct up to 9 digits. However, it\'s more important not to sum up a large number if we only want the mantissa. `10 ** functools.reduce(lambda a, b: (a + b) % 1, (math.log10(i) for i in range(1, 10 ** 6 + 1)))` gives\n```\n8.26393168831949\n```\nwhich is correct up to 11 digits.\n\n**Addendum**\nApparently [the standard solution failed for `left=184, right=70145`](https://github.com/LeetCode-Feedback/LeetCode-Feedback/issues/5657) and the most precise implementation above somehow [gives different answers on my computer vs. on LC](https://github.com/LeetCode-Feedback/LeetCode-Feedback/issues/5657#issuecomment-1001244092). The correct leading digits for `left=184, right=70145` are\n```\n391180000000002366...\n```\n`10 ** functools.reduce(lambda a, b: (a + b) % 1,...)` on my computer gives\n```\n3.9118000000001816\n```\n`10 ** (math.fsum(...) % 1)` gives\n```\n3.9117999998468442\n```\nbut `10 ** (sum(...) % 1)` gives\n```\n3.911800002992591\n```\nSo the ordering of the implementations in terms of precision doesn\'t change, but ironically in this case more precise implementation may fail to give the correct answer\uD83E\uDD37\uD83C\uDFFB\u200D\u2642\uFE0F\n\n**Addendum 2**\nUsing `np.longdouble` and vectorized `np.log10()` yields the most precise estimate so far, but it still takes some luck to err on the "right side" for the case `left=184, right=70145`:\n\n```\nimport numpy as np\n\nlog_sum = functools.reduce(lambda a, b: (a + b) % 1, np.log10(np.arange(left, right + 1, dtype=np.longdouble)))\nestimate = 10 ** (log_sum + 4)\nprint(estimate)\n```\nThe stdout:\n```\n39118.00000000122791\n```\nSolution doing this is slower and takes more memory but still fast enough to get AC.
['Python']