模运算的属性

时间:2011-04-08 13:09:42

标签: c++ c math properties modulo

我有计算和S =(a * x + b * y + c)%N。是的它看起来像二次方程但不是因为x和y有一些属性而且必须使用一些复发关系。因为总和超过了无符号long long的限制,我想知道如何使用模运算的属性来计算总和,这些属性允许写入类似的总和(我说的是因为我不记得确切这些属性如何):( a * x)%N +(b * y)%N + c%N,因此避免超过无符号长long的限制。

提前感谢您的关注! :)

6 个答案:

答案 0 :(得分:17)

a % N = x表示对于某些整数0 <= x < Nmm * N + x = a

您可以简单地推断,如果a % N = xb % N = y那么

(a + b) % N =
= (m * N + x + l * N + y) % N =
= ((m + l) * N + x + y) % N =
= (x + y) % N =
= (a % N + b % N) % N.

我们知道0 < x + y < 2N,这就是你需要保留余数的原因。这表明可以分割求和并分别计算余数然后加上它们,但不要忘记得到总和的剩余部分。

用于乘法:

(a * b) % N =
= ((m * N + x) * (l * N + y)) % N =
= ((m * l + x * l + m * y) * N + x * y) % N =
= (x * y) % N =
= ((a % N) * (b % N)) % N.

因此,您也可以对产品做同样的事情。

这些属性可以使用一些抽象代数在更一般的设置中导出(余数形成因子环Z/nZ)。

答案 1 :(得分:8)

如果需要,你可以进一步理解这个想法:

S = ( (a%N)*(x%N)+(b%N)*(y%N)+c%N )%N

答案 2 :(得分:6)

您可以按照建议将模数应用于总和的每个项;但即便如此,在总结它们之后,你必须再次应用模数来得到你的最终结果。

答案 3 :(得分:5)

这个怎么样:

   int x = (7 + 7 + 7) % 10;

   int y = (7 % 10 + 7 % 10 + 7 % 10) % 10;

答案 4 :(得分:1)

你记得对。您给出的等式,其中%N每个加数都是正确的。这正是我使用的。您还应该再次为每个部分和(和总数)%N,因为加法结果仍然可以大于N.但是要小心这只适用于您的大小限制至少是N的两倍。如果这是不是这样,它可能会变得非常讨厌。

对于部分和的以下%N次操作,你不必执行完整的除法,检查&gt; N如果更大则只减去N就足够了。

答案 5 :(得分:1)

您不仅可以在开始计算之前减少所有变量mod n,还可以使用shift-and-add方法编写自己的mod-mul来计算* x mod n,并在每一步减少结果mod n 。这样你的中间计算只需要比n多一点。计算完这些产品后,您可以在每次添加后成对添加它们并减少mod n,这也不需要超出n范围的1位。

在我对this question.的回答中有一个模块化乘法的python实现。转换为C应该是微不足道的。