inverse element of number theory

Reciprocal number theory, also known as inverse element (because I said I am used to inverse element, I will say inverse element below)

The reciprocal in number theory has a special meaning.

Do you think the reciprocal of a is still 1/a in number theory?

(・∀・) hum ~ naive

 

Let's first introduce the concept of remainder

 

(a + b) % p = (a%p + b%p) %p (pair)

(a - b) % p = (a%p - b%p) %p (pair)

(a * b) % p = (a%p * b%p) %p (pair)

(a / b) % p = (a%p / b%p) %p (wrong)

 

why division is wrong

It's hard to prove right, just give a counter example to prove wrong

(100/50)%20 = 2       ≠      (100%20) / (50%20) %20 = 0

 

For some problems, we must calculate the remainder in the middle process, otherwise the number is too large for the computer to store. If there is a division in this formula, can we not calculate this formula?

The answer is of course NO (>o<)

 

Then you need the inverse

 

we know

if

a*x = 1

Then x is the reciprocal of a, x = 1/a

But if a is not 1, then x is a decimal

In that number theory, most cases have a remainder, so now the problem has changed

a*x  = 1 (mod p)

So x must be equal to 1/a

uncertain

So at this time, we regard x as the reciprocal of a, but add a remainder condition, so x is called the inverse of a with respect to p

 

For example, 2 * 3 % 5 = 1, then 3 is the inverse of 2 to 5, or that 2 and 3 are inverses of 5 to each other

Is the effect of 3 the same as the effect of 1/2, so it is called the reciprocal of number theory

 

The inverse of a, we use inv(a) to denote

 

Then (a / b) % p = (a * inv(b) ) % p = (a % p * inv(b) % p) % p

This completely converts division into multiplication (.・ω・), and multiplication is super easy

 

 

 

 

 

 

 

 

 

The main story begins

 

How to find the inverse element

(Forgot to say that a and p are relatively prime, so a has an inverse element about p)

 

 

 

 

 

 

method one:

 

Fermat once said: A mathematician who doesn’t want to be a mathematician is not a good mathematician (( ̄▽ ̄)~*What I said casually, don’t take it seriously)

Fermat's little theorem

a^(p-1) ≡1 (mod p)

Divide both sides by a

a^(p-2) ≡1/a (mod p)

What (,,• ₃ •,,), this is number theory, dare to write 1/a

should write a^(p-2) ≡ inv(a) (mod p)

 

So inv(a) = a^(p-2) (mod p)

Find this with a quick exponentiation, the complexity is O(logn)(ง •̀_•́)ง 

copy code
1 LL pow_mod(LL a, LL b, LL p){//a的b次方求余p
 2     LL ret = 1;
 3     while(b){
 4         if(b & 1) ret = (ret * a) % p;
 5         a = (a * a) % p;
 6         b >>= 1;
 7     }
 8 return right;
 9 }
10 LL Fermat(LL a, LL p){//Fermat finds the inverse of a about b
11         return pow_mod(a, p-2, p);
12 }
copy code

 

 

 

 

 

 

 

Method Two:

 

To use the extended Euclidean algorithm

Remember Extended Euclid? (If you don’t remember, Euclid will be sad (╭ ̄3 ̄)╭♡)

 

a*x + b*y = 1

If ab is coprime, there is a solution

 

The x of this solution is the inverse of a with respect to b

y is the inverse of b with respect to a

why?

 

You see, both sides find the remainder b at the same time

 

a*x % b + b*y % b = 1 % b

a*x % b = 1 % b

a*x = 1 (mod b)

 

Look, look, it appears! ! ! (/≥▽≤/)

So x is the inverse of a with respect to b

Conversely, it can be proved that y

 

Attached code:

copy code
1 #include<cstdio>
 2 typedef long long LL;
 3 void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
 4     if (!b) {d = a, x = 1, y = 0;}
 5     else{
 6         ex_gcd(b, a % b, y, x, d);
 7 and -= x * (a / b);
 8     }
 9 }
10 LL inv(LL t, LL p){//If it does not exist, return -1
11     LL d, x, y;
12     ex_gcd(t, p, x, y, d);
13     return d == 1 ? (x % p + p) % p : -1;
14 }
15 int main(){
16     LL a, p;
17     while(~scanf("%lld%lld", &a, &p)){
18         printf("%lld\n", inv(a, p));
19     }
20 }
copy code

 

 

 

 

 

 

 

 

 

 

 

Method three:

When p is prime we have
inv(a) = (p - p / a) * inv(p % a) % p

Why is this right?

Prove that kids who don't want to watch can skip it. . . ( ̄0 ̄)

Proof:
Let x = p % a, y = p / a
then x + y * a = p
(x + y * a) % p = 0
shift the term to get x % p = (-y) * a % p
x * inv(a) % p = (-y) % p
inv(a) = (p - y) * inv(x) % p
so inv(a) = (p - p / a) * inv(p % a ) %p

Then recurse until 1, because the inverse of 1 is 1

 

Code:

copy code
1 #include<cstdio>
 2 typedef long long LL;
 3 LL inv(LL t, LL p) {//Seek the inverse of t with respect to p, note: t should be less than p, it is best to pass t%p before passing parameters
 4     return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p;
 5 }
 6 int main(){
 7     LL a, p;
 8     while(~scanf("%lld%lld", &a, &p)){
 9         printf("%lld\n", inv(a%p, p));
10     }
11 }
copy code

 

 

 

This method is not limited to finding a single inverse, it is better than the first two, it can calculate the inverse of n numbers within O(n) complexity

Recursion is the above way of writing, add a memory recursion, you can

Recursive write like this

copy code
1 #include<cstdio>
 2 const int N = 200000 + 5;
 3 const int MOD = (int)1e9 + 7;
 4 int inv[N];
 5 int init(){
 6     inv[1] = 1;
 7     for(int i = 2; i < N; i ++){
 8 inv [i] = (MOD - MOD / i) * 1ll * inv [MOD% i]% MOD;
 9     }
10 }
11 int main(){
12     init();
13 }
copy code

 

Reprinted from:

 https://www.cnblogs.com/linyujun/p/5194184.html

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324692238&siteId=291194637