质因子
质因子(质因数)是指能整除给定正整数的质数。比如说6,它的质因子是2和3。(6= 2 * 3)
质因子与因子的区别:质因子是需要能够整除给定的正整数同时它是质数。因子只要是整除给定的数,就是因子不需要是质数。
欧拉函数
1~N中与N互质的数的个数被称为欧拉函数,记为Φ(N).
Φ(N)=N*(p1-1)/p1*(p2-1)/p2*……(pm-1)/pm;(其中p1,p2……pm为N的所有质因数)
=N*(Π(1-1/p))(累乘条件(质数p|N));(|是整除符号)
证明:1).假设p是N的质因子,那么1~N中所含p的倍数有p,2p,3p,4p……[N/p] * p,一共有[N / p]个。
2).同理,假设q也是N的质因子,那么1~N中所含q的倍数有N/q个。
3).我们将p与q在1~N中的倍数所去掉,但是去掉的数当中可能含有同时是q和p倍数的数,换句话说可能有些数去掉了两次。所以,我们还需要将这些重复去掉的数给它加起来,重复去掉的数的个数为(N/p/q)。
综上3点,我们可知1~N中不与N有共同质因子p或q的数的个数为: N - N / p - N / q+N / ( p * q)=N * (1-1/p-1/q+1/p/q)=N/(1-1/p)(1-1/q);(容斥原理)
那么我们可以得到1~N中不与N含有任何共同质因子的数的个数,也就是与N互质的个数。即为Φ(N)=N*(Π(1-1/p))(累乘条件(质数p|N));(|是整除符号)
代码如下:
int phi(int n){
int 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;//把i这个质因数去掉 即这一步之后的n与现在的i互质
//防止重复计数
}
}
if(n>1)ans=ans/n*(n-1);//如果不等于1的话,最后还剩下一个质因数,
//将最后的质因数也进行相同操作
return ans;
}
接下来是欧拉函数打表的代码:
int euler(){
for(int i=2;i<=n;i++){
phi[i]=i;
}
for(int i=2;i<=n;i++){
if(phi[i]==i){
for(int j=1;j<=n;j+=i)
phi[j]=phi[j]/i*(i-1);
}
}
}
欧拉函数未优化的复杂度为O(N log N).
上面代码可以优化,变成复杂度为O(N)的
代码如下:
int v[maxn],prime[maxn],phi[maxn];
void euler(int n){
memset(v,0,sizeof v);
m=0;
for(int i=2;i<=n;i++){
if(v[i]==0){
v[i]=i,prime[++m]=i;
phi[i]=i-1;
}
for(int j=1;j<=m;j++){
if(prime[j]>v[i]||prime[j]>n/i)break;
v[i*prime[j]]=prime[j];
phi[i*prime[j]]=
phi[i]*(i%prime[j]?prime[j]-1:prime[j]);
}
}
}
这个优化是用到线性筛的思想实现的。
欧拉函数的一些性质
1).对于任意的n>1,1~n中与n互质的数的和为n*Φ(n)/2;
2).若a,b互质,则Φ(ab)=Φ(a)Φ(b)
证明:
因为gcd(n,x)=gcd(n,n-x),所以与n不互质的数x,n-x成对出现,平均值为n/2,因此与n互质的数的平均数也是n/2,进而得出性质1;
根据欧拉函数的计算式,对a,b分解质因数,直接可得性质2.把性质2推广到一般函数上,可以得到“积性函数”的性质
参考:李煜东《算法竞赛进阶指南》
非常感谢苏学长的帮助
道阻且长
自己选的路 跪着也要走完。