线性求1~n逆元

转载自 j z _ t e r r y \rm jz\_terry jz_terry的博客


简述

本文要讲的是一种 O ( n ) \mathcal{O(n)} O(n) 算法,用于求 1 ∼ n 1\sim n 1n 所有数在膜 p p p 意义下的逆元。

算法

下面给出求 x x x 在膜 p p p 意义下逆元的过程:

假设 p = a x + b p=ax+b p=ax+b ,则有 a x + b ≡ 0 ( m o d p ) ax+b\equiv 0 \pmod p ax+b0(modp)
式子两边同时除以 x b xb xb ,得 a x + b x b ≡ 0 ( m o d p ) \dfrac{ax+b}{xb}\equiv 0 \pmod p xbax+b0(modp)
整理得 a ⋅ b − 1 + x − 1 ≡ 0 ( m o d p ) a·b^{-1}+x^{-1}\equiv 0 \pmod p ab1+x10(modp)
x − 1 ≡ − a ⋅ b − 1 ( m o d p ) x^{-1}\equiv -a·b^{-1} \pmod p x1ab1(modp)
∵ p = a x + b ∵p=ax+b p=ax+b
∴ a = ⌊ p x ⌋ , b = p   m o d   x ∴a=\bigg\lfloor\dfrac px \bigg\rfloor,b=p\bmod x a=xp,b=pmodx
将其带入即得 x − 1 ≡ − ⌊ p x ⌋ × ( p   m o d   x ) − 1 x^{-1}\equiv-\bigg\lfloor\dfrac px \bigg\rfloor ×(p\bmod x)^{-1} x1xp×(pmodx)1
注意,为了避免出现负数,递推式中的 − p / x -p/x p/x 实际应是 p − p / x p-p/x pp/x

f i f_i fi 表示 i i i 在膜 p p p 意义下的逆元,则有:
f i = ( p − p / x ) × f p   m o d   i   m o d   p f_i=(p-p/x)×f_{p\bmod i}\bmod p fi=(pp/x)×fpmodimodp / / /为整除)

边界条件是 f 1 = 1 f_1=1 f1=1

这样就可以求 1 ∼ n 1 \sim n 1n 所有数在膜 p p p 意义下的逆元了


U P D   o n   2019 / 7 / 28 \rm UPD\ on\ 2019/7/28 UPD on 2019/7/28 补充一种自己口胡的证法

∵ f p   m o d   i × p   m o d   i ≡ 1 ( m o d p ) \because f_{p\bmod i}\times p\bmod i\equiv 1\pmod p fpmodi×pmodi1(modp)
∴ f p   m o d   i × ( p − ⌊ p i ⌋ × i ) ≡ 1 ( m o d p ) \therefore f_{p\bmod i}\times(p-\bigg\lfloor\dfrac pi\bigg\rfloor\times i)\equiv 1 \pmod p fpmodi×(pip×i)1(modp)
根据乘法分配律化简,得 − ⌊ p i ⌋ × i × f p   m o d   i ≡ 1 ( m o d p ) -\bigg\lfloor\dfrac pi\bigg\rfloor\times i\times f_{p\bmod i}\equiv 1\pmod p ip×i×fpmodi1(modp)
两边同乘 f i f_i fi − ⌊ p i ⌋ × f p   m o d   i ≡ f i ( m o d p ) -\bigg\lfloor\dfrac pi\bigg\rfloor\times f_{p\bmod i}\equiv f_i \pmod p ip×fpmodifi(modp)
f i ≡ − p / i × f p   m o d   i ( m o d p ) f_i \equiv -p/i\times f_{p\bmod i} \pmod p fip/i×fpmodi(modp) / / /为整除)
为避免出现负数, − p / i -p/i p/i 应变为 p − p / i p-p/i pp/i ,该变形对上式的正确性没有影响。


U P D   o n   2019 / 7 / 30 \rm UPD\ on\ 2019/7/30 UPD on 2019/7/30 补充例题及程序

例题: 洛 谷 P 3811 【 模 板 】 乘 法 逆 元 \sf 洛谷P3811 【模板】乘法逆元 P3811

就是个模板题,下面是程序

#include<cstdio>
int n,p,inv[3000010];

char cw[1<<21],t[20]; int p1,p2=-1;
inline void flush() { fwrite(cw,1,p2+1,stdout),p2=-1; }
inline void print(int x) { //快写
    if (p2>(1<<20)) flush();
    do { t[++p1]=x%10^48; }while (x/=10);
    do { cw[++p2]=t[p1]; }while (--p1);
    cw[++p2]='\n';
}

int main() {
	scanf("%d%d",&n,&p);
	inv[1]=1; puts("1");
	for (int i=2; i<=n; ++i) {
		inv[i]=1ll*inv[p%i]*(p-p/i)%p; //递推式
		print(inv[i]);
	}
	flush();
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值