模运算——竞技编程

Modular arithmetic - competitive programming

我看到很多有竞争力的程序员用 ((a + b) % d + d) % d 在 C++ 中编写代码。他们为什么不直接使用 (a + b) % d?括号内的 + d 有什么用?跟负数有关系吗?

谢谢

是的,你是对的。在 C++11 之前,余数运算符 % 对于负参数的行为留给实现,但要受到一些约束。只要该参数中的其他项总和大于或等于 -d,并且在左侧参数中添加 d 就会有所帮助,但通常情况并非如此。 (-a / d d 的倍数对于负 a 的情况在您的特定情况下会是一个更好的加法常量。)

是的,它与负数有关。它可以防止结果在某些条件下为负数。在这种情况下,当 b 变量为负数时, b % d 的结果也为负数。此结果永远不会大于 d,因此向此结果添加 d 会强制结果为正数。

以下代码为Java代码,原理相同:

int a = 13;
int b = -23;
int d = 31;

int result1 = (a + b % d + d) % d;
int result2 = (a + b % d) % d;

System.out.println(result1);
System.out.println(result2);

输出如下:

21
-10

为了避免整数溢出并始终保持数字为正,我们使用模运算。 当 a 为负数时,有竞争力的程序员倾向于使用 (a+b)%b 而不是 a%b

a%b = (a+b)%b
(a+b)%b = a%b + b%b = a%b + 0 = a%b

喜欢 a=-2 & b=5 然后 a%b = 3