如果$ax{\equiv}1(mod\,p)$,且a与p互质(gcd(a,p)=1),则称a关于模p的乘法逆元为x。(不互质则乘法逆元不存在)

基本的应用场景:有一个问题,在求解过程中有除法,答案很大,要求最终答案对某数p取模。显然,由于除法的出现,每一次运算之后取模是行不通的。(比如:求1*7/2,答案对5取模。如果每一次运算取模也就是7%5/2%5,会得到1,正确结果却是3)如果不想高精度把最终结果算出来再取模的话,有一个方法,就是把除以x转换为乘上x关于模p的乘法逆元。

此外,分数取模也是用的乘法逆元。

(事实上,乘法逆元应该视为线性同余方程的解也就是一些数而不是一个数,但是一般只需要使用任意一个(比如最小正整数解)就能完成任务)

为什么能这么做

设c是b关于模m的逆元,即$b*c{\equiv}1(mod\,m)$,那么有$a/b{\equiv}(a/b)*1{\equiv}(a/b)*b*c{\equiv}a*c(mod\,m)$


求法:

1.扩展欧几里得

$ax{\equiv}1(mod\,p)$,那么可以设$ax-1=p(-y)$,那么$ax+py=1$,而恰好$1=gcd(a,p)$,求解即可


2.欧拉定理(费马小定理)


关于欧拉函数和筛法

回顾质数筛法:

列一张表可以发现,每一个非质数x都是被(x/x的最小质因子)这个数筛掉的。

注意:break那里不能是(!i%prime[j])!!!!!如果这样写一定要写成(!(i%prime[j]))!!感叹号优先级高!!

nprime[1]=1;
for(i=2;i<=n;i++)
{
    if(!nprime[i])    prime[++len]=i;
    printf("%d: ",i);
    for(j=1;j<=len&&i*prime[j]<=n;j++)
    {
        nprime[i*prime[j]]=1;
        printf("%d ",i*prime[j]);
        if(i%prime[j]==0)    break;
    }
    puts("");
}
View Code

相关文章: