乘法逆元

若整数\(b,m\)互质,且\(b|a\),则存在一个整数,使得\(a/b\equiv a\times k(\mod m)\),称\(k\)\(b\)的模\(m\)乘法逆元,记作

\[b^{-1}(\mod m)\]

快速计算\(k\)

数据范围:

\(1\le b\le 3\times 10^{6}\)

\(b\le m\le 20000528\)

要快速求解\(k\),暴力肯定不行的。

题中指出:\(b,m\)互质,

那么,根据欧拉定理:\(b^{\varphi(m)}\equiv 1(\mod m)\),所以:

\[\therefore b^{\varphi(m)-1}\times b^{1}\equiv 1(\mod m)\]

\[\therefore b^{\varphi(m)-1}\equiv b^{-1}(\mod m)\]

\[\therefore k=b^{\varphi(m)-1}\mod m\]

\(\varphi(m)\)可以在\(O(\sqrt{m})\)的时间内算出。若\(m\)为质数,那么\(\varphi(m)\)\(=m-1\)

再使用快速幂便可以在\(\log_2\)复杂度级别快速算出。

插入:\(b,m\)必定互质

\(\text{证明:}\)

反证法。

假设\(g=\gcd(b,m)\),且\(g\ne 1\)

将原式化为:\(b\times k\equiv 1(\mod m)\)

\[\because g|b,\therefore g|(b\times k)\]

而原式中:

\[b\times k \mod m=1\]

可见原命题中的\((b\times k),m\)一定互质。

而假设中\(g\ne 1\),所以假设不成立。

\(\therefore\) \(b,m\)必定互质。

证毕。

完全积性函数

(以下用\(inv[i]\)不上\(i\)\((\mod m)\)的意义下的乘法逆元)
即:

\[inv[a]\times inv[b]\equiv inv[a\times b](\mod m)\]

证明:

\[a\times inv[a]\equiv b\times inv[b]\equiv 1(\mod m)\]

\[\therefore (a\times b)\times(inv[a]\times inv[b])\equiv 1(\mod m)\]

\[\therefore(inv[a]\times inv[b])\text{即为}(a\times b)\text{的逆元}\]

\[\therefore inv[a]\times inv[b] \equiv inv[a\times b]\]

拓展:\(b\times k\equiv h(\mod m)\)的最小正整数解

其实原理是一样的。

同样的,欧拉定理:\(b^{\varphi(m)}\equiv 1(\mod m)\)

\[\therefore b^{\varphi(m)-1}\times b\equiv 1(\mod m)\]

\[\therefore b^{\varphi(m)-1}\equiv b^{-1}(\mod m)\]

两边同时\(\times h\),得:

\[b^{\varphi(m)-1}\times h\equiv \frac{h}{b}(\mod m)\]

\[b^{\varphi(m)-1}\times h\text{即为我们要求的k的值。}\]

在线性时间快速求出\(1-n\)的乘法逆元

也就是这道题:luogu P3811 【模板】乘法逆元

用上述的算法逐个求解会爆炸,所以我们需要一个更优的算法。

引入:

做这道题之前,我们先看一个这样的问题:

\(inv[1!],inv[2!],inv[3!],...,inv[(n-1)!],inv[n!]\)\(inv[i]\)指的\(i(\mod m)\)的意义下的乘法逆元)

首先,我们求出\(1!,2!,3!,...,(n-1)!,n!(\mod m)\)

因为有如下递推关系:

\[inv[i!]=\dfrac{1}{i!}\]

\[inv[i!]\times i=\dfrac{1}{i!}\times i=\dfrac{1}{(i-1)!}=inv[(i-1)!]\]

所以,我们只要求出\(inv[n!]\),就可以\(O(n)\)逆推出所有阶乘的逆元了。

递推式:

\[inv[i!]=inv[(i+1)!]\times (i+1)!\]

回到此题:

通过\(1-n\)阶乘的逆元,我们可以快速推出:

\[inv[i]=\dfrac{1}{i}=\dfrac{(i-1)!}{i!}(\mod p)\]

Code(Luogu P3811):

#include<cstdio>
using namespace std;
const int N=3e6+15;
typedef long long ll;
int inv[N];
int fac[N];
int rf[N];//inv of fac
int n,p;

int pow(int b,int i)
{
    if(!i)return 1;
    if(i==1)return b;
    if(i%2)
    {
        int tmp=pow(b,i/2)%p;
        return ((ll)(tmp)*tmp%p*b)%p;
    }
    else
    {
        int tmp=pow(b,i/2)%p;
        return ((ll)(tmp)*tmp)%p;
    }
}

signed main()
{
    register int i;
    scanf("%d%d",&n,&p);
    fac[0]=1;
    for(i=1;i<=n;i++)
        fac[i]=(ll)(fac[i-1])*i%p;
    rf[n]=pow(fac[n],p-2)%p;
    for(i=n-1;i>=1;i--)
        rf[i]=(ll)(rf[i+1])*(i+1)%p;
    inv[1]=1;
    for(i=1;i<n;i++)
        inv[i+1]=(ll)(rf[i+1])*fac[i]%p;
    for(i=1;i<=n;i++)
        printf("%d\n",inv[i]);
    return 0;
}

转载于:https://www.cnblogs.com/-Wallace-/p/10359301.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值