欧拉函数与逆元

Phoebe ·
更新时间:2024-11-10
· 933 次阅读

欧拉函数

定义:一个正整数内(包含自身)所有与自身互质的数的个数.1与所有数互质,即phi[1]=1

几个式子

1.n为任意数,phi[n]=n*(1-1/n1)(1-1/n2)…(1-1/nn) n1到nn是n的质因子
2.如果n是一个质数 phi[n]=n-1;
3.如果n是一个奇数 phi[2n]=phi[n] (根据式子1得到)
4.如果gcd(n,m)=1,即是n与m互质,那么它们的质因子没有交集,根据1式子得到phi[n
m]=phi[n]phi[m]
5.如果n的质因子集是m的质因子集的子集,那么phi[n
m]=n*phi[m]

代码.欧拉筛 typedef long long ll; const ll N=1e7+10; ll phi[N],prime[N]; void Euler_sieve(ll n) { ll t=0; for(ll i=2;i<=n;i++){ if(phi[i]==0) phi[i]=i-1,prime[t++]=i; //式子2 for(ll j=0;j<t&&prime[j]*i<=n;j++){ // 保证线性的 if(i%prime[j]==0){ // 式子5 phi[i*prime[j]]=phi[i]*prime[j]; break; } // 式4 phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } 代码.求解单个phi[i] using ll=long long; ll Euler(ll n) { ll ans=n; for(ll i=2;i*i1) ans-=ans/n; return ans; } 欧拉定理

设a,p互质,则有
aphi[p]恒等于1%p

证明

设集合A为phi[p]里面所有与p互质的小于等于p的元素
那么设集合B为集合A中每个元素与a相乘的集合
可以证明B中集合的元素模上p的值是唯一的(任意两个元素相减得a(Ai-Aj),a与p互质,A中元素都小于等于p,相减后一定小于p,所以没有使任意两数相减模上p为0的两个数,所以唯一)
因为所有小于等于且与p互质的元素都在A中,那么集合B%p等于集合A
得 aphi[p]恒等于1%p

数论倒数(逆元)

定义:如果两个数a,b,它们的乘积模上p等于1,那么它们互为关于模数p的数论倒数
(a+b)%p=(a%p+b%p)%p
(a-b)%p=(a%p-b%p)%p 需要判断a与b的大小,如果a>b,结果要保证为正,即最后结果+p再%p,…
(a*p)%p=(a%p * b%p)%p
没有除法的

如何求解1/a关于p的逆元 费马小定理(p必须是一个质数)

因为ap-2恒等于1/a%p (p是质数)
所以可以转换成ap-2%p

ll inv1(ll a,ll mod) { ll p=mod; mod-=2; ll ans=1; while(mod) { if(mod&1) ans=(ans*a)%p; a=(a*a)%p; mod>>=1; } return ans%p; } 通过欧拉值(phi[p])求解(a与p互质)

aphi[p] 恒等于 1%p 得出 aphi[p]-1 恒等于 1/a%p

ll phi(ll n){ ll ans=n; for(ll i=2;i*i1) ans-=ans/n; return ans; } ll inv2(ll m,ll n){ ll b=phi(n)-1,ans=1; while(b){ if(b&1) ans=(ans*m)%n; m=(m*m)%n; b>>=1; } return ans; } 扩展欧几里得

扩展欧几里得存在ax+by=gcd(a,b)
如果模数是b,被摸数是a,那么上式转换为a*x%b=gcd(a,b)%b,x/gcd(a,b)%b=1/a%b
所以可以转换为x/gcd(a,b)%b 因为gcd(a,b)==1(b是质数).所以就是x%b=1/a%b
如果x是个负值,需要加上一个p

ll x,y,g; int in3(ll a,ll b) { if(!b) { x=1,y=0,g=a; return x/g; } inv2(b,a%b); ll c=x; x=y,y=c-(a/b)*y; return x/g; } 递推

设被摸数为a,模数为p,则x=p/a,y=p%a
(x*a+y)%p=0%p
y%p=(p-x)*a%p 移动时,保证两边的正负性一样
1/a%p=((p-x)*1/y)%p
1/a%p=(p-p/a)*1/(p%a))%p
求解1/a关于p的逆元, 就要求解1/(p%a)关于p的逆元
一直递归下去,直到为1,因为1的逆元就是1

void inv4(ll a,ll mod,ll num[]) { for(ll i=2; i<=a; i++) num[i]=((mod-mod/i)*num[mod%i])%mod; //num存的是逆元 }
作者:hire_candidate



欧拉 欧拉函数 函数

需要 登录 后方可回复, 如果你还没有账号请 注册新账号