如果$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(""); }