luogu problem solution P3811 [[template] multiplication inverse element]

  • Topic link:

https://www.luogu.org/problemnew/show/P3811

  • concept:

When I think of the JXOI 2018 exam room, I forgot how to fight Ni Yuan.

Recommended reading: https://www.luogu.org/blog/zjp-shadow/cheng-fa-ni-yuan

We may often encounter such a situation (such as JXOI2018 T1)

To calculate a formula similar to \(a/b\) % \(p\) , according to the congruence property, we cannot calculate it like this: $a \mod p /b \mod p $

But if it is in the ordinary formula, obviously \(a/b\) = \(a*b^-1\) .

In the sense of \(\pmod p\) , we might as well construct a \(b^-1\) such that \(b*b^-1 \equiv 1 \pmod{p}\) ;

Then \(a/b \pmod p \equiv a*b^-1 \pmod p\) , for the first question, we can safely take \(a\) % \(p\) , then multiply by \ (b\) The inverse element in the sense of \(\pmod p\) is too convenient

This leads to the definition of the inverse element:

If \(b*x \equiv 1 \pmod{p}\) and \(b, p\) are relatively prime, then \(x\) is \(b\) in the sense of \(\pmod p\) Inverse element, denoted as \(b^-1\)

  • Ideas:

There are generally three algorithms for calculating the inverse

  • Extended Euclid

    According to the definition, if the inverse of \(b\) in the sense of \(\pmod p\) is required, it is to find the x in \(b*x \equiv 1 \pmod{p}\) and convert it into a linear congruence Equation \(b*x+p*y=1\) , then just run it with Tuoou

  • Fermat's little theorem

    If p is a prime number, then for any positive integer b, there is \(b^{p} \equiv b \pmod{p}\)

    So \(b^{p-1} \equiv 1 \pmod{p}\) continue to split b to get

    \(b*b^{p-2} \equiv 1 \pmod{p}\)

    Comparing with the above definition of inverse element, we only need to find \(b^{p-2} \pmod p\)

  • Linear recurrence

    \(p=k*i+r\) 所以\(k=\left \lfloor \frac{p}{i} \right \rfloor,r=p \mod i\)

    So \(k*i+r \equiv 0 \pmod p\) is also multiplied by \(i^-1,r^-1\)

    \(k*r^-1+i^-1 \equiv 0 \pmod p\) Shift term

    \(i^-1 \equiv -k*r^-1 \pmod p\)

    \(i^-1 \equiv -\left \lfloor \frac{p}{i} \right \rfloor*{(p \mod i)}^-1\pmod p\)

    We store all inverses in the inv[] array, then

    inv[i]=-((p/i)*inv[p%i]%p); while(inv[i]<0)inv[i]+=p;
    Of course inv[1]=1;

  • Code:

  • Tuoou + Fermat's little theorem

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define LL long long 
using namespace std;
LL mod(LL a,LL b)
{
    if(a<b)return a;
    if(a==b)return 0;
    else return a-a/b*b;
}
LL pow_mod(LL a, LL b, LL p){//a的b次方求余p 
    LL ret = 1;
    while(b){
        if(b & 1) ret = mod((ret * a) ,p);
        a =mod((a * a) ,p);
        b >>= 1;
    }
    return ret;
}
LL Fermat(LL a, LL p){//费马求a关于b的逆元 
        return pow_mod(a, p-2, p);
}
void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
    if (!b) {d = a, x = 1, y = 0;}
    else{
        ex_gcd(b, mod(a,b), y, x, d);
        y -= x * (a / b);
    }
}
LL inv(LL t, LL p){//如果不存在,返回-1 
    LL d, x, y;
    ex_gcd(t, p, x, y, d);
    return d == 1 ? (mod(x,p) + p) % p : -1;
}
int main()
{
    int op;
    LL a,p;
    cin>>a>>p;
    for(int i=1;i<=a;i++)cout<<inv(i,p)<<endl;
    return 0;
}
  • Linear recurrence
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
#deinfe ll long long 
using namespace std;
const int maxn=3000005;
int n,p;
ll inv[maxn];
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=getchar()))ne=c=='-';
    x=c-48;
    while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;
    return ;
}
inline void make_inv(){
    printf("1\n");   //inv[1];
    for(register int i=2;i<=n;i++){
        inv[i]=-((p/i)*inv[p%i]%p);
        while(inv[i]<0)inv[i]+=p;
        printf("%lld\n",inv[i]);
    }
    return ;
}
int main()
{
    read(n),read(p);
    inv[1]=1;
    make_inv();
    return 0;
}

Guess you like

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