【问题标题】:How to correctly use Mod 10^9+7如何正确使用 Mod 10^9+7
【发布时间】:2017-04-09 12:12:35
【问题描述】:

在Java中,我需要计算前n个数字的平方和,即

1^2 + 2^2+ 3^2+.....+n^2

这是

n(n+1)(2n+1)/6   

n^3/3 + n^2/2 + n/6

那我需要计算另一个值

n*(n-1/2)^2

因为 n 会很大,所以答案可以是“answer%M”,其中 M 是 10^9+7。

我无法理解应该在哪个计算点进行操作 %M。例如

n%M * (n+1)%M (2n+1)%M /  6 

(n(n+1)(2n+1)/6)%M

你能帮帮我吗?总的来说,请提供使用 %M 的指南;以便我下次再决定。

【问题讨论】:

  • 这一定是以前问过的。可能很难搜索10 ^ 9 + 7。你可以试试1000000007

标签: java algorithm modulo largenumber


【解决方案1】:

(n(n+1)(2n+1)/6)%M 理论上是正确的,n%M * (n+1)%M * (2n+1)%M / 6 是不正确的。

如果n很大,(n(n+1)(2n+1)/6)的中间计算会溢出你的整数类型,所以第一种方法也不尽如人意。

计算a*b/c % M 的一般解决方案是计算cmodular inverseM(比如c'),然后计算:((a%M * b%M)%M * c')%M

在这里,它要简单一些,因为您要除以常数 (6),并且可以在三个项中找到并剔除 2 和 3 的因数。类似这样的伪代码:

n1 := n
n2 := n+1
n3 := 2n+1
if n1 % 2 == 0 { n1 /= 2 } else { n2 /= 2 }
if n1 % 3 == 0 { n1 /= 3 } else if n2 % 3 == 0 { n2 /= 3 } else { n3 /= 3}
return (((n1 % M) * (n2 % M)) % M * (n3 % M)) % M

【讨论】:

  • 对于简单的常数,您可以使用 wolfram alpha 来计算这个逆。例如,6^-1 mod 10^9+7 = 166666668。
  • 你为什么不这样做 .. else if n2 %2 ==0 (n2 /=2 } else {n3 /=2} .... 任何具体原因?
  • 哦..知道了..如果 n%2 不是 0 那么它是奇数,所以 n+1 肯定是偶数。所以 n2%2 肯定会为零
  • n3 总是奇怪的。 n1n2 中的一个恰好是偶数。 n1n2n3 中的一个可以被 3 整除。
  • 如果你的模是素数,并且是 10^9+7 的情况,那么你可以使用公式 c^(M-2) mod M 来计算 c mod M 的模逆,这可以通过快速 pow 轻松完成。
【解决方案2】:

/运算符不能进行模除:(a/b) % M != ((a % M)/(b % M)) % M,所以只需要在末尾取模即可:

(n*(n+1)*(2n+1)/6) % M

更多信息请阅读Modulo operation。并且不要忘记使用BigInteger 类来计算非常大的数字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 2013-02-12
    • 2017-11-11
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 2017-05-20
    相关资源
    最近更新 更多