【问题标题】:How to compute this modulus when there is an integer overflow整数溢出时如何计算此模数
【发布时间】:2014-01-04 04:59:10
【问题描述】:
(10^{17}-1)*(10^{17}-1) mod 10^{18}

我正在解决一个编程问题,我将整数保存在 64 位长整数中。以上是我无法解决的特殊情况。 (ab)mod m = (a mod m)(b mod m) mod m, 在这里不成立,因为 (a mod m)(b mod m) 仍然会溢出 64 位整数。我该如何解决这个问题?我仅以 17 次方为例。这个问题甚至适用于 (10^{10}, 10^{18}-1) 范围内的所有整数。

编辑:我正在使用 C++ 来解决这个问题。这个问题可以在不使用处理大整数的库的情况下解决。

【问题讨论】:

标签: math numbers modulo


【解决方案1】:

你可以使用你引用的身份,你只需要另一个类似的身份:(a+b) mod m = (a mod m) + (b mod m)

目标是乘以 x*y mod m 而没有任何中间值超过溢出限制(在本例中为 2^64),其中 x 的起始值小于 m(如果不是,则减少它 mod @ 987654325@)、y 可能大于m,并且x*y 可能会溢出。如果m 小于溢出限制的一半,我们可以这样做。

解决方案很简单:只需对x*y 逐位执行基本乘法,然后对m 进行模数运算。

xy 开始小于m(如果不是,请先减少它)。以a_0 * 2^0 + a_1 * 2^1 + a_2 * 2^2 + ... 的形式写入y,其中a_n 为0 或1(表示该术语是否存在)。 (又名,以二进制形式写y。)现在我们有了:

x * (a_0 * 2^0 + a_1 * 2^1 + a_2 * 2^2 + ...) mod m

y的每个条款上分配x

(x * a_0 * 2^0) + (x * a_1 * 2^1) + (x * a_2 * 2^2) + ... mod m

然后使用原始乘法恒等式:对于上述每个项,将 x 乘以 2 mod m,直到您达到该项所需的 2 次方。 (因为x < m2 * m < 2^64,然后2 * x < 2^64,所以我们可以乘以2 而不会溢出。)完成后,将每个术语的结果相加m(您可以随时保持运行总和) )。

这些操作都不会超过 2^64,因此不会溢出。这适用于任何小于 2^64 / 2 = 2^63 的 m 值以及小于 m 的任何整数 xy

这不一定是最快的方法,请随意寻找更有效的方法。对于初学者来说,m 与溢出限制相比越小,我们可以将y 重写为的项的基数就越大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-24
    • 2019-06-15
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 2012-08-09
    相关资源
    最近更新 更多