【问题标题】:division by a number of multiplication of integers of an array and take the modulo除以数组整数的乘法数并取模
【发布时间】:2018-03-29 08:31:18
【问题描述】:

我遇到了这个问题,就像下面的问题

您有一个包含 n 个整数的数组(整数可以大到 10^9)并且您有 q 个查询,每个查询都有一个数组索引,因此您必须将数组相乘而无需该特定索引的整数和那么你有一个数字,m,然后,你必须以这个数字 m(最多 10^9)取模,并给出每个查询的结果。

e.g. suppose you have an array of n = 5 integers
            1,2,3,4,5
and you have q = 3 queries 1,3, 5 and mod value m = 100.
for 1st query: (2*3*4*5) mod 100 = 20
for 2nd query: (1*2*4*5) mod 100 = 40
for 3rd query: (1*2*3*4) mod 100 = 24
so output is 20,40,24

我不想让代码告诉我应该是最佳的方法。

【问题讨论】:

  • 在实际问题中是m素数?
  • 您的问题的答案取决于 m 与列表中的整数之间的关系。 m是素数吗? m 与列表中的所有数字互质吗?如果其中任何一个是这样,那么就有一种快速而简单的算法。如果不是或者你不知道,最好的算法会更慢但仍然可行。
  • 不,m 不是素数

标签: arrays math modulo


【解决方案1】:

计算数组中所有整数的乘积。存储它。

int product = 1*2*3*4*5;

现在对于每个查询,您的计算很简单

(product/query) %100; 

【讨论】:

  • 产品可以很快变得很大。简单的整数数据类型是不够的,BigIntegers 会很慢。
  • 我说整数可以大到 10^9,所以所有这些整数的乘积会导致溢出,所以这不是一个好的解决方案。
【解决方案2】:

我可以想到一种解决方案,它涉及在相对较小的数字上递归使用模运算符。此解决方案可能需要很长时间来计算,但它应该能够轻松避免您遇到的溢出类型。

我们可以利用模运算的以下特性:

(a*b) mod c = ((a mod c)*b) mod c

请参阅下面的简单示例。它使用相对较小的数字(远小于您会遇到的溢出),但它证明了这一点。


(5*4*3*2*1) mod 7

按照“传统方式”计算:

120 mod 7 = 1

但是,假设我们不能使用 120 这样大的数字。

我们可以这样做:

(5) mod 7 = 5   (take this result as input to next line)
            |
            |
 +----------+
 |
 |
(5*4) mod 7 = 20 mod 7 = 6 
                         |
                         |
 +-----------------------+
 |
 |
(6*3) mod 7 = 18 mod 7 = 4
                         |
                         |
 +-----------------------+
 |
 |
(4*2) mod 7 = 8 mod 7 = 1
                        |
                        |
 +----------------------+
 |
 |
(1*1) mod 7 = 1 mod 7 = 1  <--this is final result

请注意,上面的最终结果 (1) 与直接计算 120 mod 7 的结果相同。然而,我们在任何计算中使用的最大数字只有20

还有一点需要注意:对于这种方法,如果任何中间结果曾经是0,那么最终结果也必须是0


编辑

如果你需要处理更小的数字,你可以使用模算术的以下属性(这实际上只是上面已经显示的内容的扩展):

a*b mod c = ((a mod c)*(b mod c)) mod c

通过这样做,而不是处理像a*b 这样大的数字,您将只处理像(a mod c)*(b mod c) 这样大的数字,它必须小于或等于(c-1)^2(因为x mod c 必须是小于或等于c-1)。当然,处理更小的数字的代价是您的代码会更复杂并且执行时间会稍长。

【讨论】:

  • 我不确定是否还有其他选择。
  • 我能想到的唯一可能加快计算时间(但会增加内存使用)的另一件事是让您的程序利用存储查找表的数据库(甚至只是一个文本文件)模运算的解决方案。因此,您的程序不需要每次都计算模数,它只需在文本文件中查找值。
猜你喜欢
  • 1970-01-01
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多