简体   繁体   中英

modulo formula in C++

I Have this formula: (n - 1)! ((n (n - 1))/2 + ((n - 1) (n - 2))/4) 2<=n<=100000 I would like to modulate the result of this from this formula by any modulo, but for the moment let's assume that it is constant, MOD = 999999997 . Unfortunately I can't just calculate the result and modulate it, because unfortunately I don't have variables larger than 2^64 at my disposal, so the main question is. What factors to modulate by MOD to get the results%MOD? Now let's assume that n=19 . What is in brackets is equal to 247.5

18! = 6402373705728000 18! = 6402373705728000 . (6402373705728000 * 247.5)mod999999997 = 921442488 . Unfortunately, in case I modulate 18, first, the result will be wrong, because (18.)mod999999997 = 724935119. (724935119 * 247.5)mod9999997 = 421442490. How to solve this problem?

I think the sum could be break down. The only tricky part here is that (n - 1)(n - 2)/4 may have a .5 decimal., as n(n-1) / 2 will always be integer.

S = (n - 1)!  * ((n (n - 1))/2 + ((n - 1) (n - 2))/4)
  = [(n-1)!  * (n*(n-1)/2)] + [(n-1)! * (n-1)(n-2)/4]
  = A + B

A is easy to do. With B , if (n-1)(n-2) % 4 == 0 then there's nothing else either, else you can simplified to X/2 , as (n-1)(n-2) is also divisible by 2.

If n = 2 , it's trivial, else if n > 2 there's always a 2 in the representation of (N-1). = 1x2x3x... xN (N-1). = 1x2x3x... xN . In that case, simply calculate ((N-1)./2) = 1x3x4x5x... xN .

Late example:

N = 19
MOD = 999999997

--> 18! % MOD = 724935119 (1)
    (18!/2) % MOD = 862467558 (2)

    n(n-1)/2 = 171 (3)
    (n-1)(n-2)/2 = 153 (4)

--> S = (1)*(3) + (2)*(4) = 255921441723
    S % MOD = 921442488

On another note, if mod is some prime number, like 1e9+7 , you can just apply Fermat's little theorem to calculate multiplicative inverse as such:

(a/b) % P = [(a%P) * ((b^(P-2)) % P)] % P (with P as prime, a and b are co-prime to P)

You will have to use 3 mathematical formulas here:

(a + b) mod c == (a mod c + b mod c) mod c

and

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

But those are only valid for integers. The nice part here is that formula can only be integer for n >= 2, provided you compute it as:

 (((n - 1)! * n * (n - 1))/2) + (((n - 1)! * (n - 1) * (n - 2))/4)
    1st part is integer       |         2nd part is too

for n == 2, first part boils down to 1 and second is 0

for n > 2 either n or n-1 is even so first part is integer, and again eithe n-1 of n-2 is even and (n-1). is also even so second part is integer. As your formula can be rewritten to only use additions and multiplications it can be computed

First of All, for n=2 we can say that the result is 1. Then, the expression is equal to: (n*(n-1) (n-1)!)/2 + (((n-1) (n-2)/2)^2)*(n-3). .

lemma: For every two consecutive integer number, one of them is even.

By lemma we can understand that n*(n-1) is even and also (n-1)*(n-2) is even too. So we know that the answer is an integer number.

First we calculate (n*(n-1) (n-1).)/2 modulo MOD. We can calculate (n (n-1))/2 that can be saved in a long long variable like x, and we get the mod of it modulo MOD:

x = (n*(n-1))/2;
x %= MOD;

After that for: i (n-1 -> 1) we do:

x = (x*i)%MOD; 

And we know that both of 'x' and 'i' are less than MOD and the result of multiplication can be save in a long long variable.

And likewise we do the same for (((n-1) (n-2)/2)^2) (n-3). , We calculate (n-1)*(n-2)/2 that can be save in a long long variable like y: and we get the mod of it modulo MOD:

y = ((n-1)*(n-2))/2;
y %= MOD;

And after that we replace (y^2)%MOD on y because we know that y is less than MOD and y*y can be save in a long long variable:

y = (y*y)%MOD;

Then like before for: i (n-3 -> 1) we do:

y = (y*i)%MOD;

And finally the answer is (x+y)%MOD

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM