- 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;
}