先来看看(a/b)%c 这个问题 不妨引入一个新的概念来让其等于1/b
切入正题:
若
,gcd(a,b)=1
则称x为a模p的乘法逆元 记x为inv(a)或者a^-1 (a p互质)
(概念性的东西讲完了,那么他有什么存在的意义呢?)
先看看下面这个符号
“≡ ” 简单说明一下 ....a≡ b(mod c)等价于a(mod c)=b(mod c)
费马小定理+快速幂
int ans=1; while (b) { if (b&1)///b为奇数 ans=(ans*a)%p; a=(a*a)%p;///b为偶数 b>>=1; } return ans;
直接令b=p-2 求解就行(不会快速幂可以去写luogu p1226)
裴蜀定理内容
ax+by=c,x∈Z∗,y∈Z∗成立的充要条件是gcd(a,b)∣c。Z表示正整数集
即c%gcd(a,b)=0 显然贝祖方程有解
ax≡1mod p 等价于 ax+bp=1 x要有解 则a,p互质 gcd(a,p)=1
a mod p=a- [a/p]*p;(减去p的倍数)
ax1+by1=ay2+b[x2-[a/b]y2]
证明:
a*x1 + b*y1 = gcd(a,b)
b*x2+(a%b)*y2 = gcd(b,a%b)
由欧几里得算法 gcd(a,b)=gcd(b,a%b)
a*x1 + b*y1 = b*x2+(a- [a/b]*b)*y2
化简得证
b=0时x=1,y=0
gcd(a,0)=a
上代码
int _exgcd(int a,int b,int &x,int &y)///x代表解 { if (!b) { x=1; y=0; return a ; } int gcd=_exgcd(b,a%b,x,y); int tmp=x; x=y; y=tmp-(a/b)*y; return gcd;//返回最大公约数 }
void _exgcd(int a,int b,int &x,int &y) { if (!b) { x=1; y=0; return ; } _exgcd(b,a%b,x,y);///x在调用之前值已经修改 int tmp=x; x=y; y=tmp-(a/b)*y; }
线性逆元递推求法
p=ka+q -> k=[p/a]->ka+q ≡ 0mod p
两边同时乘以a和q的逆元k*q^-1+a^-1≡ 0mod p
a^-1≡ -k*q^-1(mod p)
a^-1≡ -[p/a]*q^-1(mod p)
a^-1≡ -(p/a)*(p%a)^-1(mod p)
inv[i]=(p-(p/i))*inv[p%i]%p
#include <bits/stdc++.h> #define int long long using namespace std; int inv[3000010]; signed main() { int n,p; scanf("%lld%lld",&n,&p); inv[1]=1; printf("1\n"); for (int i=2;i<=n;++i) { inv[i]=(p-p/i)*inv[p%i]%p; printf("%lld\n",inv[i]); } return 0; }
权当笔记
(差距一步步扩大,而我还在原地徘徊)
如有不足,评论区指正
///x在调用之前值已经修改