码迷,mamicode.com
首页 > 其他好文 > 详细

欧拉函数

时间:2018-08-07 13:07:06      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:memset   整数   +=   while   i++   for   大于   理解   sqrt   

问:求小于n等于且与n互素的正整数的个数

两个整数互素即:两个数gcd为1

解:

根据唯一分解定理,大于1的整数均可看成若干素数的乘积的形式

若n=1,答案为1;

若n>1;

可以这样考虑:

把n看成若干素数的乘积n=p1^k1*p2^k2*···*pm^km;(p1,p2,···,pm均为素数)(k1,k2,···,km均为非负整数)S1={p1,p2,···,pm}

那么对于满足条件的数s必有s=q1^t1*q2^t2*···*ql^tl;(q1,q2,···,qm均为素数)(t1,t2,···,tm均为非负整数)S2={q1,q2,···,qm}

s1∩S2为空集;

那么即1~n-1中所有素因子不包含S1中的数即符合题意,但是这样做太麻烦了,可以反过来考虑,

把不符合条的数去掉即可,这个可以用容斥原理解决

首先n减掉小于n且为S1中元素倍数的数量

n-n/p1-n/p2-···-n/pk;

再加上小于n且为S1中两个不同元素乘积的的数量

n-n/p1-n/p2-···-n/pm+n/(p1*p2)+n/(p1*p3)+···+n/(p(m-1)*pm);

再减去小于n且为S1中三个不同元素乘积的数量

·······

最终得到φ(n)=Σ(s?{ p1,p2,pm }(-1)^|S|*n/∏(pi∈S)pi;

但是这个公式有2^n次方项,有时不如暴力;

但是我们可以将它变形,φ(n)=n(1-1/p1)(1-1/p2)···(1-1/pm);

将上述公式展开正好符合推导过程;

根据这个我们可以编码实现

euler(int n)
{
int m=(int)sqrt(n+0.5);
int ans=n;
for(int i=2; i<=m; i++)
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0)n/=i;
}
if(n>1)
ans=ans/n*(n-1);
return ans;
}

 求1到n的欧拉函数值,不用一个一个计算,这样考虑,对于1~n中的任意一个素数p,其小于等于n的倍数的欧拉函数都必须乘以(p-1)/p,那么我们对于1~n所有的素数都将其倍数乘以这个值,再遍历完全部素数后,1~n的欧拉函数值都已经计算过了;

编码实现

<span>

void phi_seive(int n){
memset(phi,0,sizeof(phi));
phi[1]=1;
for(int i=2;i<=n;i++)
if(!phi[i]){
for(int j=i;j<=n;j+=i){
if(!phi[j])phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}

</span>

欧拉函数

标签:memset   整数   +=   while   i++   for   大于   理解   sqrt   

原文地址:https://www.cnblogs.com/RGBTH/p/9429298.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!