线性同余与乘法逆元

欧几里得算法

∀ a , b ∈ N , gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) \forall a,b\in \N,\gcd(a,b)=\gcd(b,a\bmod b) a,bN,gcd(a,b)=gcd(b,amodb)
证明:
考 虑 记 a 与 b 的 公 因 数 为 d ∵ ∃ t , k , r ∈ N , b = t ⋅ d , a = k ⋅ ( t ⋅ d ) + r ∵ d ∣ b , d ∣ a ∴ ∃ x ∈ N , x ⋅ d = a = k ⋅ ( t ⋅ d ) + r ⇔ x = k ⋅ ( t ⋅ d ) + r d = k t + r d ∵ x ∈ N ∴ d ∣ r ∴ d ∣ ( a   m o d   b ) ∴ a   m o d   b 的 因 数 集 与 a 与 b 的 公 因 数 集 相 同 ∴ gcd ⁡ ( a , b ) = gcd ⁡ ( b , b   m o d   a ) 考虑记a与b的公因数为d\\\because \exist t,k,r\in\N,b=t\cdot d,a=k\cdot (t \cdot d)+r\\\because d\mid b,d\mid a\\\therefore \exist x\in\N,x\cdot d=a=k⋅(t⋅d)+r\\\quad \Leftrightarrow x=\dfrac{k⋅(t⋅d)+r}{d}=kt+\dfrac{r}{d}\\\because x\in \N\\\therefore d\mid r\\\therefore d\mid (a\bmod b)\\\therefore a\bmod b 的因数集与a与b的公因数集相同\\\therefore \gcd(a,b)=\gcd(b,b\bmod a) abdt,k,rN,b=td,a=k(td)+rdb,daxN,xd=a=k(td)+rx=dk(td)+r=kt+drxNdrd(amodb)amodbabgcd(a,b)=gcd(b,bmoda)

此算法也常称为辗转相除法。

#include<bits/stdc++.h>
using namespace std;
int a,b;
int gcd(int x,int y)
{
	if(y==0) return x;
	int r=x%y;
	return gcd(y,r);
}
int main()
{
	cin>>a>>b;
	cout<<gcd(a,b);
	return 0;
}

裴蜀定理

对 于 a , b ∈ N , x , y ∈ Z , 则 关 于 x , y 的 不 定 方 程 有 对于a,b\in \N,x,y\in\Z,则关于x,y的不定方程有 a,bNx,yZx,y
a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)

证明:
先 考 虑 证 明   a x + b y 的 和 为 gcd ⁡ ( a , b ) 倍 数 ∵ ∃ x ′ , y ′ ∈ N , a = x ′ ⋅ gcd ⁡ ( a , b ) , b = y ′ ⋅ gcd ⁡ ( a , b ) ∴ a x + b y = x ⋅ x ′ gcd ⁡ ( a , b ) + y ⋅ y ′ gcd ⁡ ( a , b )     = gcd ⁡ ( a , b ) ⋅ ( x x ′ + y y ′ ) ∴ gcd ⁡ ( a , b ) ∣ ( a x + b y ) ∴ ∀ t ∈ Z , a x + b y = t ⋅ gcd ⁡ ( a , b ) 先考虑证明~ax+by 的和为\gcd(a,b)倍数\\\because \exist x',y'\in\N,a=x'\cdot\gcd(a,b),b=y'\cdot\gcd(a,b)\\\therefore ax+by=x\cdot x'\gcd(a,b)+y\cdot y'\gcd(a,b)\\\qquad\qquad\,\,\,=\gcd(a,b)\cdot(xx'+yy')\\\therefore \gcd(a,b)\mid (ax+by)\\\therefore \forall t\in\Z,ax+by=t\cdot \gcd(a,b)  ax+bygcd(a,b)x,yN,a=xgcd(a,b),b=ygcd(a,b)ax+by=xxgcd(a,b)+yygcd(a,b)=gcd(a,b)(xx+yy)gcd(a,b)(ax+by)tZ,ax+by=tgcd(a,b)

显然只有当等式右边为 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)倍数时才存在整数解。


扩展欧几里得算法

我们再来考虑如何找到这个不定方程的一个特解。

考 虑 当 b = 0 时 , 显 然 有 一 对 ( x , y ) , 使 得 ( x , y ) = ( 1 , 0 ) 时 满 足 要 求 , 即 a + 0 = gcd ⁡ ( a , 0 ) 考 虑 当 b ≠ 0 时 , 根 据 欧 几 里 得 算 法 , 有 gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) ∴ ∃ x ′ , y ′ ∈ Z ,   a x + b y = b x ′ + ( a   m o d   b ) y ′      = b x ′ + ( a − ⌊ a b ⌋ ⋅ b ) y ′      = b x ′ + a y ′ − ⌊ a b ⌋ b y ′      = a y ′ + b ( x ′ − ⌊ a b ⌋ y ′ ) x = y ′ y = x ′ − ⌊ a b ⌋ y ′ 考虑当 b=0时,显然有一对(x,y),使得(x,y)=(1,0)时满足要求,即a+0=\gcd(a,0)\\考虑当b\ne 0时,根据欧几里得算法,有 \gcd(a,b)=\gcd(b,a\bmod b)\\\therefore \exist x',y'\in \Z,\, ax+by=bx'+(a\bmod b)y'\\ \,\,\,\,=bx'+(a-\left\lfloor\dfrac{a}{b}\right\rfloor \cdot b)y'\\ \,\,\,\,=bx'+ay'-\left\lfloor\dfrac{a}{b}\right\rfloor by'\\\,\,\,\,=ay'+b(x'-\left\lfloor \dfrac{a}{b}\right\rfloor y')\\x=y'\\\quad y=x'-\left\lfloor\dfrac{a}{b}\right\rfloor y' b=0(x,y)使(x,y)=(1,0)a+0=gcd(a,0)b=0,,gcd(a,b)=gcd(b,amodb)x,yZ,ax+by=bx+(amodb)y=bx+(abab)y=bx+aybaby=ay+b(xbay)x=yy=xbay

因此,只需求出 x ′ , y ′ x',y' x,y就可以得到 x , y x,y x,y,而 x ′ , y ′ x',y' x,y可以由方程右边为 gcd ⁡ ( b , a   m o d   b ) \gcd(b,a\bmod b) gcd(b,amodb) 时得到,这不就是一个欧几里得算法的递归过程吗?我们往上层层递归,直到当b为0时我们就可以得到 ( x , y ) = ( 1 , 0 ) (x,y)=(1,0) (x,y)=(1,0),然后我们就可以运用上述公式递归求得 ( x , y ) (x,y) (x,y)

解决这种不定方程的问题常在欧几里得算法中实现,因此被称为扩展欧几里得算法,也称为 e x g c d exgcd exgcd

#include <bits/stdc++.h>
using namespace std;
int a,b;
int x,y;
int exgcd(int l,int r)
{
	if(r==0)
	{
		x=1;
		y=0;
		return l;
	}
	int d=exgcd(r,l%r);
	int t=x;
	x=y;
	y=t-l/r*y;
	return d;
}
int main()
{
	cin>>a>>b;
	int ans=exgcd(a,b);
	cout<<x<<" "<<y<<" "<<ans;
	return 0;
} 

继续观察这个不定方程,此时我们已经可以用上述算法找到一个特解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),我们现在来思考如何得到这个不定方程的通解。

我 们 考 虑 从 方 程 的 特 解 入 手 , 现 在 我 们 已 经 拥 有 了 两 个 不 定 方 程 : 1. a x + b y = gcd ⁡ ( a , b ) 2. a x 0 + b y 0 = gcd ⁡ ( a , b ) 由   1   式 减 去   2   式 得 :   a ( x − x 0 ) + b ( y − y 0 ) = 0 ⇔ a ( x − x 0 ) = b ( y 0 − y ) 考 虑 等 式 两 边 同 时 除 以 gcd ⁡ ( a , b )   a gcd ⁡ ( a , b ) ( x − x 0 ) = b gcd ⁡ ( a , b ) ( y 0 − y )   显 然 有 a gcd ⁡ ( a , b ) 与 b gcd ⁡ ( a , b ) 互 质   ∴ ∀ t ∈ Z , x − x 0 = t ⋅ b gcd ⁡ ( a , b ) , y 0 − y = t ⋅ a gcd ⁡ ( a , b )   ∴ x = x 0 + t ⋅ b gcd ⁡ ( a , b ) y = y 0 − t ⋅ a gcd ⁡ ( a , b ) 我们考虑从方程的特解入手,现在我们已经拥有了两个不定方程:\\\mathbb{1.}ax+by=\gcd(a,b)\\\mathbb{2.}ax_0+by_0=\gcd(a,b)\\由~\mathbb{1}~式减去~\mathbb{2}~式得:~a(x-x_0)+b(y-y_0)=0\\\Leftrightarrow a(x-x_0)=b(y_0-y)\\考虑等式两边同时除以\gcd(a,b)\\~\\\dfrac{a}{\gcd(a,b)}(x-x_0)=\dfrac{b}{\gcd(a,b)}(y_0-y)\\~\\显然有\dfrac{a}{\gcd(a,b)}与\dfrac{b}{\gcd(a,b)}互质\\~\\\therefore \forall t\in\Z,x-x_0=t\cdot \dfrac{b}{\gcd(a,b)},y_0-y=t\cdot \dfrac{a}{\gcd(a,b)}\\~\\\therefore x=x_0+t\cdot \dfrac{b}{\gcd(a,b)}\\\quad y=y_0-t\cdot\dfrac{a}{\gcd(a,b)} 1.ax+by=gcd(a,b)2.ax0+by0=gcd(a,b) 1  2  a(xx0)+b(yy0)=0a(xx0)=b(y0y)gcd(a,b) gcd(a,b)a(xx0)=gcd(a,b)b(y0y) gcd(a,b)agcd(a,b)b tZxx0=tgcd(a,b)by0y=tgcd(a,b)a x=x0+tgcd(a,b)by=y0tgcd(a,b)a

于是我们就得到了由不定方程特解得到通解的方法。

接下来我们再来扩展一下,考虑如何求出不定方程中 x x x 的最小非负整数解。

考 虑 到 我 们 是 从 x = x 0 + t ⋅ b gcd ⁡ ( a , b ) 得 到 所 有 的 x 的 , 因 此 , 想 要 求 最 小 的 非 负 整 数 x , 实 际 上 是 要 满 足 以 下 式 子   x 0 + t ⋅ b gcd ⁡ ( a , b ) ≥ 0 , x 0 + ( t + 1 ) ⋅ b gcd ⁡ ( a , b ) ≤ 0 由 于 t 可 取 任 意 整 数 , 因 此 上 述 式 子 等 价 于 x 0 − t ⋅ b gcd ⁡ ( a , b ) ≥ 0 , x 0 − ( t + 1 ) ⋅ b gcd ⁡ ( a , b ) ≤ 0   很 显 然 , 此 时 最 小 的 x 非 负 整 数 值 可 以 由 x 0   m o d   b gcd ⁡ ( a , b ) 得 到 但 考 虑 到 x 0 有 可 能 是 负 数 , 此 时 我 们 应 该 考 虑 如 何 将 负 数 取 模 转 换 为 正 数 取 模   对 于 负 数 x   m o d   m 的 值 , 考 虑   m o d   的 性 质 , 这 个 式 子 等 价 于 ( ( x   m o d   m ) + m )   m o d   m   因 此 我 们 考 虑 对 ( x 0   m o d   b gcd ⁡ ( a , b ) ) + b gcd ⁡ ( a , b ) 来 确 保 式 子 永 远 为 正 数 , 后 在 对 其 取   m o d     因 此 , x 的 最 小 非 负 整 数 解 为 ( ( x 0   m o d   b gcd ⁡ ( a , b ) ) + b gcd ⁡ ( a , b ) )   m o d   b gcd ⁡ ( a , b ) 考虑到我们是从 x=x_0+t\cdot\dfrac{b}{\gcd(a,b)} 得到所有的x的,因此,想要求最小的非负整数x,实际上是要满足以下式子\\~\\x_0+t\cdot\dfrac{b}{\gcd(a,b)}\ge0,x_0+(t+1)\cdot\dfrac{b}{\gcd(a,b)}\le 0\\由于t可取任意整数,因此上述式子等价于\\x_0-t\cdot\dfrac{b}{\gcd(a,b)}\ge0,x_0-(t+1)\cdot\dfrac{b}{\gcd(a,b)}\le 0\\~\\很显然,此时最小的x非负整数值可以由x_0\bmod \dfrac{b}{\gcd(a,b)}得到\\但考虑到x_0有可能是负数,此时我们应该考虑如何将负数取模转换为正数取模\\~\\对于负数x\bmod m的值,考虑\bmod 的性质,这个式子等价于((x\bmod m)+m)\bmod m\\~\\因此我们考虑对(x_0\bmod \dfrac{b}{\gcd(a,b)})+\dfrac{b}{\gcd(a,b)}来确保式子永远为正数,后在对其取\bmod\\~\\因此,x的最小非负整数解为 ((x_0\bmod \dfrac{b}{\gcd(a,b)})+\dfrac{b}{\gcd(a,b)})\bmod \dfrac{b}{\gcd(a,b)} x=x0+tgcd(a,b)bxx x0+tgcd(a,b)b0,x0+(t+1)gcd(a,b)b0tx0tgcd(a,b)b0,x0(t+1)gcd(a,b)b0 xx0modgcd(a,b)bx0 xmodmmod((xmodm)+m)modm (x0modgcd(a,b)b)+gcd(a,b)bmod x((x0modgcd(a,b)b)+gcd(a,b)b)modgcd(a,b)b

例题
https://www.luogu.com.cn/problem/P1516


线性同余方程

给定正数 a , b , m a,b,m a,b,m,求一个整数 x x x满足 a ⋅ x ≡ n ( m o d b ) a\cdot x\equiv n\pmod b axn(modb),或者无解。
由于未知数是一次的,因此我们称 a x ≡ n ( m o d b ) ax\equiv n\pmod b axn(modb) 为线性同余方程(一次同余方程)。

我 们 考 虑 同 余 方 程 a x ≡ n ( m o d b ) , 则 定 有 b ∣ ( a x − n ) 因 此 有 y ∈ Z , 使 得 a x − n = b y , 即 a x − b y = n , 由 于 y 可 取 任 意 整 数 , 因 此 等 价 于 a x + b y = n 我们考虑同余方程 ax\equiv n\pmod b,则定有b\mid(ax-n)\\因此有y\in\Z,使得ax-n=by,即ax-by=n,由于y可取任意整数,因此等价于 ax+by=n axn(modb)b(axn)yZ,使axn=byaxby=nyax+by=n

于是我们就将同余方程转换为了一个不定方程,此方程当且仅当 gcd ⁡ ( a , b ) ∣ n \gcd(a,b)\mid n gcd(a,b)n 时存在整数解。
当存在整数解时,我们可以通过扩展欧几里得算法求出不定方程 a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)时的一个特解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)
由于 n = n gcd ⁡ ( a , b ) ⋅ gcd ⁡ ( a , b ) , n=\dfrac{n}{\gcd(a,b)}\cdot \gcd(a,b), n=gcd(a,b)ngcd(a,b)因此不定方程 a x + b y = n ax+by=n ax+by=n的特解即为 ( x 0 ⋅ n gcd ⁡ ( a , b ) , y 0 ⋅ n gcd ⁡ ( a , b ) ) (x_0\cdot \dfrac{n}{\gcd(a,b)},y_0\cdot \dfrac{n}{\gcd(a,b)}) (x0gcd(a,b)n,y0gcd(a,b)n)
转换可得线性同余方程 a x ≡ n ( m o d b ) ax\equiv n\pmod b axn(modb) 的一个特解 x 0 ⋅ n gcd ⁡ ( a , b ) x_0\cdot \dfrac{n}{\gcd(a,b)} x0gcd(a,b)n

一个定理:

对 于 一 个 线 性 同 余 方 程 a x ≡ n ( m o d b ) 对于一个线性同余方程ax\equiv n\pmod b 线axn(modb),都有 gcd ⁡ ( a , b ) 个   m o d   b 不 同 余 的 解 , 若 已 知 第 一 个 解 为 x 0 , 则 x i = x 0 + i ⋅ b gcd ⁡ ( a , b ) , i ∈ Z , 0 ≤ i < gcd ⁡ ( a , b ) 。 \gcd(a,b)个\bmod b不同余的解,若已知第一个解为x_0,则x_i=x_0+i\cdot \dfrac{b}{\gcd(a,b)},i\in\Z,0\le i<\gcd(a,b)。 gcd(a,b)modbx0xi=x0+igcd(a,b)biZ,0i<gcd(a,b)

证明:
考 虑 证 明 x i = x 0 + i ⋅ b gcd ⁡ ( a , b ) 是 方 程 的 解 : ∵ a x i ≡ n ( m o d b ) ⇔ a ( x 0 + i ⋅ b gcd ⁡ ( a , b ) ) ≡ n ( m o d b ) ⇔ a x 0 + a ⋅ i ⋅ b gcd ⁡ ( a , b ) ≡ n ( m o d b ) ⇔ a x 0 + i ⋅ lcm ⁡ ( a , b ) ≡ n ( m o d b ) ∵ i ⋅ lcm ⁡ ( a , b )   m o d   b = 0 ∴ a x 0 + i ⋅ lcm ⁡ ( a , b ) ≡ a x 0 ( m o d b ) ∴ a x i ≡ a x 0 ≡ n ( m o d b ) 因 此 x i = x 0 + i ⋅ b gcd ⁡ ( a , b ) 是 方 程 的 解   ∵ 0 ≤ i < gcd ⁡ ( a , b ) ∴ 0 ≤ i ⋅ b gcd ⁡ ( a , b ) < b ∴ x 0 ⋯ i 显 然   m o d   b 互 不 同 余 , 且 有 gcd ⁡ ( a , b ) 个 解 考虑证明x_i=x_0+i\cdot \dfrac{b}{\gcd(a,b)}是方程的解:\\\because ax_i\equiv n\pmod b\\\Leftrightarrow a(x_0+i\cdot \dfrac{b}{\gcd(a,b)})\equiv n\pmod b\\\Leftrightarrow ax_0+a\cdot i\cdot \dfrac{b}{\gcd(a,b)}\equiv n\pmod b\\\Leftrightarrow ax_0+i\cdot \operatorname{lcm}(a,b)\equiv n\pmod b\\\because i\cdot \operatorname{lcm}(a,b)\bmod b=0\\\therefore ax_0+i\cdot \operatorname{lcm}(a,b)\equiv ax_0\pmod b\\\therefore ax_i\equiv ax_0\equiv n\pmod b\\因此x_i=x_0+i\cdot \dfrac{b}{\gcd(a,b)}是方程的解\\~\\\because0\le i<\gcd(a,b)\\\therefore 0\le i\cdot \dfrac{b}{\gcd(a,b)}<b\\\therefore x_{0\cdots i}显然\bmod b互不同余,且有\gcd(a,b)个解 xi=x0+igcd(a,b)baxin(modb)a(x0+igcd(a,b)b)n(modb)ax0+aigcd(a,b)bn(modb)ax0+ilcm(a,b)n(modb)ilcm(a,b)modb=0ax0+ilcm(a,b)ax0(modb)axiax0n(modb)xi=x0+igcd(a,b)b 0i<gcd(a,b)0igcd(a,b)b<bx0imodbgcd(a,b)

#include<bits/stdc++.h>
using namespace std;
int a,n,b;
int x,y;
int exgcd(int l,int r)
{
	if(r==0)
	{
		x=1;
		y=0;
		return l;
	}
	int d=exgcd(r,l%r);
	int t=x;
	x=y;
	y=t-l/r*y;
	return d;
}
void mod_slover()
{
	int g=exgcd(a,b);
    if(n%g!=0) exit(0);//判断是否有解 
    x=(x*(n/g))%b;
    x=x*(n/g);  //求解 
    x=((x%(b/g))+(b/g))%(b/g);  //取得最小正整数解 
    for(int i=0;i<g;i++)
    {
  	  cout<<x+i*(b/g)<<endl;
    }
    //枚举g个不同余的解 
}
int main()
{
  cin>>a>>n>>b;
  mod_slover();
  return 0;
}

例题
https://www.luogu.com.cn/problem/P1082
https://www.luogu.com.cn/problem/P5656


乘法逆元

或许乘法逆元有一个更加感性的理解:同余方程余数意义下的倒数

考 虑 a , b , m ∈ Z , gcd ⁡ ( b , m ) = 1 , 若 存 在 x ∈ Z , 且 满 足 a b ≡ a x ( m o d m ) , 则 称 x 为 b 的 乘 法 逆 元   若 a b ≡ a x ( m o d m ) , 则 有 a ≡ a b x ( m o d m ) ⇔ b x ≡ 1 ( m o d m ) , 因 此 这 也 是 乘 法 逆 元 的 一 种 定 义 。 考虑a,b,m\in\Z,\gcd(b,m)=1,若存在x\in\Z,且满足\dfrac{a}{b}\equiv ax\pmod m,则称x为b的\color{Blue}乘法逆元\\~\\\color{Black}若\dfrac{a}{b}\equiv ax\pmod m,则有a\equiv abx\pmod m\Leftrightarrow \color{Blue}bx\equiv 1\pmod m,\color{Black}因此这也是乘法逆元的一种定义。 a,b,mZ,gcd(b,m)=1,xZbaax(modm)xb baax(modm)aabx(modm)bx1(modm)

因此我们就可以通过解 b x ≡ 1 ( m o d m ) bx\equiv 1\pmod m bx1(modm)这个线性同余方程,得到最小正数解 x x x,便得到 b b b的乘法逆元。

知道了这么个名字就很酷的东西有什么用呢?观察乘法逆元的第一个定义,有了它我们就可以处理有理数取余(特别是当 a , b a,b a,b特别大的情况下,同余性质很重要)。

不想贴了,就是求线性同余方程的解

利用 b b b   m o d   m \bmod m modm意义下的乘法逆元 b − 1 b^{-1} b1,我们可以得到 a b   m o d   m \dfrac{a}{b}\bmod m bamodm的值,即为 a b − 1   m o d   m ab^{-1}\bmod m ab1modm

例题
https://www.luogu.com.cn/problem/P2613

线性求逆元

考虑给出 p p p,若要求 [ 1 , p ] [1,p] [1,p]内所有数在   m o d     p \bmod~p mod p意义下的乘法逆元,是否具有复杂度优的递推公式呢?

考 虑 求 i 的 乘 法 逆 元 , 则 有 ∃ k , r ∈ Z , p = k ⋅ i + r , 显 然 k ⋅ i + r ≡ 0 ( m o d p ) 将 同 余 方 程 两 边 同 时 乘 以 i 的 逆 元 i − 1 k ⋅ ( i ⋅ i − 1 ) + r ⋅ i − 1 ≡ 0 ( m o d p ) k + r ⋅ i − 1 ≡ 0 ( m o d p ) 移 项 得 r ⋅ i − 1 ≡ − k ( m o d p ) 再 尝 试 将 r 消 掉 , 于 是 乘 以 r − 1 i − 1 ≡ − k ⋅ r − 1 ( m o d p ) 考 虑 k = ⌊ p i ⌋ , r = p   m o d   i , 带 入 i − 1 ≡ − ⌊ p i ⌋ ⋅ ( p   m o d   i ) − 1 ( m o d p ) 考 虑 − ⌊ p i ⌋   m o d   p 可 以 转 换 为 p − ⌊ p i ⌋   i − 1 ≡ ( p − ⌊ p i ⌋ ) ( p   m o d   i ) − 1 ( m o d p ) 考虑求i的乘法逆元,则有\exist k,r\in \Z,p=k\cdot i+r,显然\\k\cdot i+r\equiv 0\pmod p\\将同余方程两边同时乘以 i 的逆元 i^{-1}\\k\cdot (i\cdot i^{-1})+r\cdot i^{-1}\equiv 0\pmod p\\k+r\cdot i^{-1}\equiv0\pmod p\\移项得\\r\cdot i^{-1}\equiv -k\pmod p\\再尝试将r消掉,于是乘以r^{-1}\\i^{-1}\equiv-k\cdot r^{-1}\pmod p\\考虑k=\left\lfloor\dfrac{p}{i}\right\rfloor,r=p\bmod i,带入\\i^{-1}\equiv-\left\lfloor\dfrac{p}{i}\right\rfloor\cdot(p\bmod i)^{-1}\pmod p\\考虑-\left\lfloor\dfrac{p}{i}\right\rfloor \bmod p可以转换为 p-\left\lfloor\dfrac{p}{i}\right\rfloor\\~\\i^{-1}\equiv (p-\left\lfloor\dfrac{p}{i}\right\rfloor)(p\bmod i)^{-1}\pmod p ik,rZp=ki+rki+r0(modp)ii1k(ii1)+ri10(modp)k+ri10(modp)ri1k(modp)rr1i1kr1(modp)k=ipr=pmodii1ip(pmodi)1(modp)ipmodppip i1(pip)(pmodi)1(modp)

考虑使用 i n v i inv_i invi 表示 i i i p p p意义下的乘法逆元,将 ( m o d p ) \pmod p (modp)提出来,得
i n v i = ( p − ⌊ p i ⌋ ) ( p   m o d   i ) − 1   m o d   p inv_i=(p-\left\lfloor\dfrac{p}{i}\right\rfloor)(p\bmod i)^{-1}\bmod p invi=(pip)(pmodi)1modp

这就是逆元的递推式,我们就可以线性求逆元了。

#include<bits/stdc++.h>
using namespace std;
int p;
int inv[100010];
int main()
{
  cin>>p;
  inv[1]=1;
  for(int i=2;i<=p;i++)
    inv[i]=(p-p/i)*inv[p%i]%p;
  for(int i=1;i<=p;i++)
    cout<<inv[i]<<endl;
  return 0;
}

当然,我们也可以考虑利用费马小定理来求乘法逆元

由 于 当 p 为 质 数 时 , 有 a p ≡ a ( m o d p ) ∴ a p − 1 ≡ 1 ( m o d p ) ⇔ a ⋅ a p − 2 ≡ 1 ( m o d p ) 由于当p为质数时,有a^p\equiv a\pmod p\\ \therefore a^{p-1}\equiv 1\pmod p\Leftrightarrow a\cdot a^{p-2}\equiv 1\pmod p papa(modp)ap11(modp)aap21(modp)
因此有当 p p p为质数时, a p − 2   m o d   p a^{p-2}\bmod p ap2modp a a a   m o d   p \bmod p modp意义下的乘法逆元。
我们可以使用快速幂优化求 a p − 2 a^{p-2} ap2的过程,因此我们可以得到一个 Θ ( n log ⁡ 2 n ) \Theta(n\log_2n) Θ(nlog2n)求逆元的算法。

#include<bits/stdc++.h>
#define int long long
using namespace std;
long long n,p;
long long inv[30000010];
long long ksm(int a,int b)
{
	long long ans=1;
	while(b)
	{
		if(b&1) ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans;
}
signed main()
{
  cin>>n>>p;
  cout<<1<<'\n';
  for(int i=2;i<=n;i++)
  {
  	cout<<ksm(i,p-2)<<'\n';
  }
  return 0;
}

例题
https://www.luogu.com.cn/problem/P3811


总结

例题:
https://www.luogu.com.cn/problem/P5431

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值