定义:对于正整数n,φ(n)是小于或等于n的正整数中,与n互质的数的数目;
公式:φ(n)=n*(1-1/p1)*(1-1/p2)…(1-1/pn); 其中p1,p2, …,pn为与n的质因子
因为任意正整数都可以唯一表示成如下形式:
n=p1^k1*p2^k2*……*pi^ki;(即分解质因数形式)
φ(n)=(p1-1)*p^(k1-1)*(p2-1)*p^(k2-1) …(pn-1)*p^(kn-1)
=n*(1-1/p1)*(1-1/p2)…(1-1/pn);//证明如2
其中φ(1)=1;
1,若p是质数,Φ(p)=p-1;
2,若n是质数p的k次幂,φ(n)= (p-1)p^(k-1)
因为除了p的倍数都与n互质,φ(n)=p^k-(是p的倍数的数的个数);
而是p的倍数的数有:(1*p+2*p+3*p+…+p^(k-1)*p)共p^(k-1)个
所以φ(n)= p^k-p^(k-1)=(p-1)p^(k-1);
3,欧拉函数是积性函数,若m,n互质,φ(mn)= φ(m)φ(n);
在程序中利用欧拉函数如下性质,可以快速求出欧拉函数的值(a为N的质因素)
1,若(N%a==0 && (N/a)%a==0)则有:E(N)=E(N/a)*a;
2,若(N%a==0 && (N/a)%a!=0)则有:E(N)=E(N/a)*(a-1);因为N/a与a互质,所以由性质3可得到这样的结果。其中因为a是素数,如果(N/a)%a!=0则就说明N/a与a互质。
3,特殊性质:当n为奇数时,φ(2n)=φ(n), 证明与上述类似。
4,欧拉函数值为偶数
欧拉函数的计算方法:
1,
doublesum=n;
for(inti=0;i<cnt&&prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
sum=sum*(1-1.0/prime[i]);
}
}
2,利用素数筛选
voidgetsolve()
{
getprime();
memset(temp,0,sizeof(temp));
for(inti=0;i<cnt;i++)
temp[prime[i]]=prime[i]-1;
temp[1]=1;
for(inti=2;i<N;i++)
{
if(!temp[i])
{
for(intj=0;j<cnt&&prime[j]<=i;j++)
{
if(i%prime[j]==0)
{
intv=i/prime[j];
if(temp[v])
{
if(v%prime[j]==0)
{
temp[i]=temp[v]*prime[j];
}
else
{
temp[i]=temp[v]*(prime[j]-1);
}
break;
}
}
}
}
}
}
例题:
hdu1286 找新朋友
#include<cstdio>
#include<cstring>
#include<algorithm>
usingnamespacestd;
#defineN 32768
boolp[N];
intprime[N/2],cnt;
voidgetprime()
{
cnt=0;
fill(p,p+N,1);
for(inti=2;i<N;i++)
{
if(p[i])
{
for(intj=i+i;j<N;j+=i)
p[j]=0;
}
}
for(inti=2;i<N;i++)
if(p[i]) prime[cnt++]=i;
}
intmain()
{
intt,n;
getprime();
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
doublesum=n;
for(inti=0;i<cnt&&prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
sum=sum*(1-1.0/prime[i]);
}
}
printf("%d\n", int(sum));
}
return 0;
}
hdu2824 The Euler function
#include<cstdio>
#include<cstring>
#include<algorithm>
usingnamespacestd;
#defineN 3000000
inttemp[N];
intcnt,prime[N/2];
boolp[N];
__int64sum;
voidgetprime()
{
fill(p,p+N,1);
cnt=0;
for(inti=2;i<N;i++)
{
if(p[i]) prime[cnt++]=i;
for(intj=0;j<cnt&&prime[j]*i<N;j++)
{
p[prime[j]*i]=0;
if(i%prime[j]==0) break;
}
}
}
voidgetsolve()
{
getprime();
memset(temp,0,sizeof(temp));
for(inti=0;i<cnt;i++)
temp[prime[i]]=prime[i]-1;
temp[1]=1;
for(inti=2;i<N;i++)
{
if(!temp[i])
{
for(intj=0;j<cnt&&prime[j]<=i;j++)
{
if(i%prime[j]==0)
{
intv=i/prime[j];
if(temp[v])
{
if(v%prime[j]==0)
{
temp[i]=temp[v]*prime[j];
}
else
{
temp[i]=temp[v]*(prime[j]-1);
}
break;
}
}
}
}
}
}
intmain()
{
inta,b;
getsolve();
while(scanf("%d%d",&a,&b)!=EOF)
{
sum=0;
for(inti=a;i<=b;i++)
sum+=temp[i];
printf("%I64d\n",sum);
}
return 0;
}