问题
If I have 2 int
or long long
variables, call them a
and b
, and I want to compute the sum (a + b) mod p
, where p is a large prime integer, how can I utilize the modulo operator in C++ to achieve the desired result?
I have tried (a + b) % p
, but this gives overflow sometimes, since a + b
will overflow before the mod is applied.
Other similar approaches I have tried seem to avoid overflow, but give an incorrect result.
How can I use the modulo operator in this case to correctly compute the desired sum, while avoiding overflow?
回答1:
a %= p
b %= p
c = p-a
if(b==c)
sum = 0
if (b<c)
sum = a+b
if (b>c)
sum = b-c
EDIT: The trick is to avoid any calculation that might cause overflow, without knowing where the limit is. All we know is that the given a, b and p are below the limit -- maybe just below the limit.
After the first two steps (a%=p;b%=p;
) we know a<p
and b<p
. We still daren't add a+b
, because that sum might exceed p and break the limit*. But we can see how much room we have left with c = p-a
, which is safe because we know that c<=p
and c>0
. (The stated types are unsigned, but we may as well avoid negative numbers, if only because their limits are sometimes off by one from the negatives of the positive limits, in ways I can never remember.)
If b=c, then b=p-a, so a+b=p, so the sum (mod p) is zero.
If b<c
, then a+b<p
, so we can safely compute a+b
(and need not apply the modulo).
if b>c
, then it is not safe to compute a+b
, but we know that the number we're looking for is a+b-p
, which we can rewrite as b-(p-a)
, and we already have b
and p-a
, so we can safely perform that subtraction.
(*) That's right, I said "daren't". It's a perfectly good word.
回答2:
There is a distributive rule, but you have to apply the mod operator a last time. See this answer for the math.
So (a + b) % p
becomes ( (a % p) + (b % p) ) % p
.
来源:https://stackoverflow.com/questions/61923686/modulus-function-to-avoid-integer-overflow-in-c