欧拉函数(详细证明+推导) 每日一遍,算法再见!

欧拉函数

定义:对于一个正整数n,n的欧拉函数 ϕ ( n ) \phi(n) ϕ(n),表示小于等于n与n互质的正整数的个数

性质

性质1:如果n是质数,那么 ϕ ( n ) = n − 1 \phi(n)=n-1 ϕ(n)=n1,因为只有n本身与它不互质。

性质2:如果p,q都是质数,那么 ϕ ( p ∗ q ) = ϕ ( p ) ∗ ϕ ( q ) = ( p − 1 ) ∗ ( q − 1 ) \phi(p*q)=\phi(p)*\phi(q)=(p-1)*(q-1) ϕ(pq)=ϕ(p)ϕ(q)=(p1)(q1).

性质2推导: p , 2 p , 3 p , . . . . , ( q − 1 ) ∗ p 有 q − 1 个 数 整 除 p ∗ q , 同 理 q , 2 q , 3 q , . . . , ( p − 1 ) ∗ q 有 p − 1 个 数 可 以 整 除 p q , 再 加 上 p q 本 身 能 整 除 p q , 那 么 丢 掉 这 些 数 剩 余 的 数 就 与 p q 互 质 , 一 共 有 p q − ( q − 1 + p − 1 + 1 ) = ( p − 1 ) ( q − 1 ) 。 p,2p,3p,....,(q-1)*p有q-1个数整除p*q,同理q,2q,3q,...,(p-1)*q有p-1个数可以整除pq,再加上pq本身能整除pq,那么丢掉这些数剩余的数就与pq互质,一共有pq-(q-1+p-1+1)=(p-1)(q-1)。 p,2p,3p,....,(q1)pq1pqq,2q,3q,...,(p1)qp1pq,pqpqpqpq(q1+p1+1)=(p1)(q1)

性质3:根据性质2得出,如果p是质数,那么 ϕ ( p k ) = p k − p k − 1 \phi(p^k)=p^k-p^{k-1} ϕ(pk)=pkpk1

性质推导: p , 2 p , 3 p , . . . , p k − 1 p , 一 共 p k − 1 个 数 能 够 整 除 p k p,2p,3p,...,p^{k-1}p,一共p^{k-1}个数能够整除p^k p,2p,3p,...,pk1p,pk1pk
那么丢到这些数,剩下的 p k − p k − 1 p^k-p^{k-1} pkpk1就与 p k p^k pk互质。

性质4:对于任意正整数n, ϕ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) ( 1 − 1 p 3 ) . . . . ( 1 − 1 p n ) , 其 中 p 1 , p 2 , p 3 , . . . , p n 是 n 的 质 因 子 \phi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})(1-\frac{1}{p_3})....(1-\frac{1}{p_n}),其中p_1,p_2,p_3,...,p_n是n的质因子 ϕ(n)=n(1p11)(1p21)(1p31)....(1pn1)p1,p2,p3,...,pnn,这个性质可以由性质2和性质3联合推导出来,这里我就不推了,大家自行推导。

性质5:若a为质数,b mod a=0, ϕ ( a ∗ b ) = ϕ ( b ) ∗ a \phi(a*b)=\phi(b)*a ϕ(ab)=ϕ(b)a
性质6:若a,b互质, ϕ ( a ∗ b ) = ϕ ( b ) ∗ ϕ ( a ) \phi(a*b)=\phi(b)*\phi(a) ϕ(ab)=ϕ(b)ϕ(a)
性质7:若n为一个正整数,那么 ∑ d ∣ n = n , d ∣ n 表 示 d 整 除 n \sum_{d|n}=n,d|n表示d整除n dn=ndndn

模板

求单个欧拉函数

代码:

单个欧拉函数公式
phi(n)=1*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)*....*(1-1/pn);
其中p1,p2,p3...pn是n的质因子
#include<iostream>
#include<cmath> 
using namespace std;
typedef long long ll;
int main()
{
	ll n;
	scanf("%lld",&n);
	ll ans=n;
	for(int i=2;i<=sqrt(n);i++)
	{
		if(n%i==0)
		{
			ans=ans/i*(i-1);
			while(n%i==0)
			{
				n/=i;
			}
		}
	}
	if(n>1) ans=ans/n*(n-1);//说明还有一个质因数没算,不然的花n应该为1
	printf("%lld",ans);
	return 0;
}

通过欧拉筛求欧拉函数

#include<iostream>
#include<cstring>
using namespace std;
const int Maxn=1e7;
int phi[Maxn];//记录数的约数个数(欧拉函数) 
bool vis[Maxn];//记录数字是否访问 
int prime[Maxn];//保存素数 
int main()
{
	memset(vis,false,sizeof(vis));
	memset(phi,0,sizeof(phi));
	memset(prime,0,sizeof(prime));
	int n;
	scanf("%d",&n);
	vis[1]=1;//1不是素数 
	for(int i=2;i<=n;i++)
	{
		if(!vis[i])//没有被访问,也就是没有被筛掉,说明是素数 
		{
			vis[i]=!vis[i];
			prime[++prime[0]]=i;
            phi[i]=i-1;
		}
		for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++)
		{
			vis[i*prime[j]]=true;
			if(i%prime[j]==0)//a%b==0,那么phi[a*b]=b*phi[a] 
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			else phi[i*prime[j]]=phi[i]*(prime[j]-1);//两者互素 
		}
	}
	printf("%d\n",prime[0]);
	for(int i=1;i<=prime[0];i++)
	{
		printf("%d %d\n",prime[i],phi[prime[i]]);
	}
	return 0;
}

请关注我看更多数论分支知识体系讲解,也别忘点个赞额

  • 15
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值