【问题标题】:Avoiding sum, multiplication overflow with modulo用模避免求和、乘法溢出
【发布时间】:2020-07-29 14:35:30
【问题描述】:

我尝试解决一些简单的算法任务,但遇到了模运算问题。

我需要计算这种操作: (100003 - 200003*x + 300007*x*x*x) % 1000000

当然,300007*x*x*x200003*x 都可以轻松溢出 1000000,所以我需要对所有部分“制作”模数。

我找到了这样的东西:Sum and multiplication modulo 并试图“在每一步之后都做一个 mod P”。像这样:

res = 100003
res = (100003 - 200003*x) % 1000000) % 1000000
...

正确吗?因为我没有得到正确的结果。

【问题讨论】:

  • 你能展示你的实际代码,输入会产生错误的结果吗?
  • 它不能在 python 中溢出,所以你正在使用的平台很重要。但是,是的,您所做的应该可以工作,除非即使是单个乘法也会导致溢出。
  • res,x 是什么数据类型(位,有符号)? x 是什么值? google modadd,modsub,modmul 你很可能在200003*x 期间溢出,所以你需要一个propper modmul,它需要双倍的位宽来获得子结果。为了避免这种情况,您可以使用 Karatsuba 或 Naive O(n^2) 乘法...如果 x 真的很大,您可以改用 200003*(x%1000000) 但如果您使用 32 位,它可能会在没有 modmul 的情况下轻松溢出跨度>

标签: algorithm math overflow modulo


【解决方案1】:

要计算(100003 - 200003*x + 300007*x*x*x) % 1000000 我会这样做:

  1. y = x % 1000000
  2. res = (100003 - (200003 * y) % 1000000 + (((300007 * y) % 1000000) * y) % 1000000) * y) % 1000000
  3. if (x > 0 && res
  4. if (x 0) res -= 1000000

公式的编写方式我们知道结果必须与 x 具有相同的符号。这可能是您出错的地方,您省略了第 3 步和第 4 步。尽管如前所述,使用 32 位它仍然会溢出。如果您需要正模,则可以省略第 4 步,如果 res 为负,则只需添加 1000000。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    相关资源
    最近更新 更多