我有计算和S =(a * x + b * y + c)%N。是的它看起来像二次方程但不是因为x和y有一些属性而且必须使用一些复发关系。因为总和超过了无符号long long的限制,我想知道如何使用模运算的属性来计算总和,这些属性允许写入类似的总和(我说的是因为我不记得确切这些属性如何):( a * x)%N +(b * y)%N + c%N,因此避免超过无符号长long的限制。
提前感谢您的关注! :)
答案 0 :(得分:17)
a % N = x
表示对于某些整数0 <= x < N
和m
:m * N + x = a
。
您可以简单地推断,如果a % N = x
和b % 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应该是微不足道的。