在数论,对正整数n,欧拉函数是1~n的数中与n互质的数的数目,我们记为 ,(后面欧拉定理中会用到)。此函数以其首名研究者欧拉命名。例如 ,因为1,3,5,7均和8互质。
求解公式:
现假设
有
个质因子p1、p2、p3、、、pr,则:
即
欧拉函数的两个性质:来自欧拉函数及其证明(这两个性质可以推出上面的公式)
- 欧拉函数既然是积性函数,就说明如果n可以分解成两个互质的整数之积,
,则
- 如果n是质数的某一个次方,即n = pk (p为质数,k为大于等于1的整数),则
1、单独求某个欧拉函数值代码:
int fn(int x)
{
int ans=x;
for(int i=2; i<=sqrt(x); i++)
{
if(x%i==0)
{
ans-=ans/i;
while(x%i==0)
x/=i;
}
}
if(x>1)
ans-=ans/x;
return ans;
}
2、既然跟n的所有质因子有关,那么就可以利用之前筛素数的知识:埃氏筛法和欧拉筛
2.1 求1~n的欧拉函数值:
//埃氏筛法中每个合数会被它的每个质因子筛一遍,就完美地求出欧拉函数值了
bool vis[manx];
void make_prime(int n)
{
memset(vis,0,sizeof(vis));
vis[0]=vis[1]=1;
for(int i=1;i<=n;i++)
ans[i]=i;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
for(int j=i;j<=n;j+=i)
{
vis[j]=1;
ans[j]=ans[j]*(i-1)/i;//主角在这里
}
}
}
}
2.2 求1~n的欧拉函数值:
原理:以下证明来自欧拉线性筛(筛质数,求欧拉函数)
那么,为了求可以在可以在线性时间内求出来所有的欧拉函数,需要事先知道三个性质:
对于一个质数 :
性质1: ;
因为p为质数,而从1到 ,只有 与 自本身不互质,其余的 个数字都与 互质,因此得出性质1;
性质2:对于 % ;
性质3:对于 % ,
利用了欧拉函数的积性。而又通过性质1可知, ,因此 ;
这个,本人才疏学浅,看了各种证明,但还是不明白性质2,性质3是怎么得出来的,所以先当作结论记住吧。
知道了这三个结论之后,在配合欧拉筛筛质数,就可以得出范围内所有的数字的欧拉函数。
代码:
void make_prime(int n)
{
int cou=0,ans[manx];
memset(prime,0,sizeof(prime));
memset(vis,0,sizeof(vis));
vis[0]=vis[1]=1;
for(int i=2; i<=n; i++)
{
if(!vis[i])
{
prime[cou++]=i;
ans[i]=i-1;//改动部分1(对应性质1)
}
for(int j=0; j<cou; j++)
{
if(i*prime[j]>n)
break;
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
ans[i*prime[j]]=ans[i]*prime[j];//改动部分2(对应性质2)
break;
}
else
ans[i*prime[j]]=ans[i]*ans[prime[j]];//改动部分3(对应性质3)
//或者写成ans[i*prime[j]]=ans[i]*(prime[j]-1);
}
}
}
例题:Farey Sequence
感想:质因子是个神奇的存在