您的位置:首页 > 其它

欧拉函数小结

2015-10-29 17:39 316 查看
欧拉函数:小于等于n的与n互质的数。

求法:因为任何数都可以表示成n = p1^a1*p2^a2*·····pi^ai

可以推出eular(n)=n*(1-1/p1)*(1-1/p2)········(1-1/pi);

因为对于每一个质因子,比如2,那么在小于n的数中,与n不互质的,与其公约数是2的倍数的占其1/2,所以乘上1/2就是剩下与n公约数不含2的,然后依次类推,对于每个n的约数,乘上(pi-1/pi),最后的答案就是欧拉函数值了。

求单个欧拉函数:

int eular(int n)
{
int ret=n,a=n;
for(int i=2;i<=n;i++)
{
if(a%i==0)
{
ret=ret/i*(i-1);//先除防止溢出
while(a%i==0)
a/=i;
}
}
if(a>1)
ret=ret/a*(a-1);
return ret;
}


多个欧拉函数,打表,和素数筛差不多

const int maxn=1e7;
int phi[maxn];
int main()
{
for(int i=1;i<maxn;i++)
phi[i]=i;
for(int i=2;i<maxn;i+=2)
phi[i]/=2;
for(int i=3;i<maxn;i+=2)
{
if(phi[i]==i)
for(int j=i;j<maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
}


hdu2824 http://acm.hdu.edu.cn/showproblem.php?pid=2824

连续的求和,打表省时间

#include <iostream>

using namespace std;
const int maxn = 3000001;
int phi[maxn];
void init()
{
for(int i=1;i<=maxn;i++)
phi[i]=i;
for(int i=2;i<=maxn;i+=2)
phi[i]/=2;
for(int i=3;i<=maxn;i+=2)
{
if(phi[i]==i)
for(int j=i;j<=maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
}
}
int main()
{init();
int a,b;
long long sum;
while(cin>>a>>b)
{
sum=0;
for(int i=a;i<=b;i++)
sum+=phi[i];
cout<<sum<<endl;
}

return 0;
}


http://acm.hdu.edu.cn/showproblem.php?pid=1787

求小于n的gcd(i,n)大于1的个数,欧拉函数直接求gcd(i,n)==1的个数 用n减即可。

http://acm.hdu.edu.cn/showproblem.php?pid=3501

求小于n的与n不互质的数的和。

首先欧拉函数可以求出小于n的与n互质的数的个数,然后我们可以发现这样一个性质,当x与n互质时,n-x与n互质,那么所有小于n与n互质的数总是可以两两配对使其和为n,这也就是为什么当n大于2时欧拉函数都是偶数,知道这一点后,就可以计算出小于n与n互质的数的和了,那么不互质的和只要用总和来减就可以了。

#include <iostream>

using namespace std;
typedef long long LL;
LL eular(LL n)
{
LL ret=n,a=n;
for(LL i=2;i*i<=n;i++)
{
if(a%i==0)
ret=ret/i*(i-1);
while(a%i==0)
a/=i;
}
if(a>1)
ret=ret/a*(a-1);
return ret;
}
int main()
{LL n;
while(cin>>n&&n)
{
long long ans=n*(n+1)/2-n;
ans-=eular(n)*n/2;
cout<<ans%1000000007<<endl;
}

return 0;
}


http://acm.hdu.edu.cn/showproblem.php?pid=2588

求X满足1<=X<=N gcd (X,N)>=M

先求出N的约数,p1,p2····pi存起来,对于每一个大于等于M的约数,有gcd(k*pi,n)=pi>=M,即eular(n/pi)

#include <iostream>
#include <cstdio>
using namespace std;
int eular(int n)
{
int ret=n,a=n;
for(int i=2;i*i<=n;i++)
{
if(a%i==0)
ret=ret/i*(i-1);
while(a%i==0)
a/=i;
}
if(a>1)
ret=ret/a*(a-1);
return ret;
}
int main()
{int t,n,m;
int p[10000];
cin>>t;
while(t--)
{int ans=0,cnt=0,i;
scanf("%d%d",&n,&m);
for(i=1;i*i<n;i++)
if(n%i==0)
p[cnt++]=i,p[cnt++]=n/i;
if(n%i==0)
p[cnt++]=i;
for(i=0;i<cnt;i++)
if(p[i]>=m)
ans+=eular(n/p[i]);
printf("%d\n",ans);
}

return 0;
}


http://acm.hdu.edu.cn/showproblem.php?pid=4983

求满足gcd(n−a,n)*gcd(n−b,n)=n^k.

k>2时无解k=2时唯一解a=b=k

上式=gcd(a,n)*gcd(b,n)=n

k=1,枚举n的约数

#include <iostream>

using namespace std;
typedef long long LL;
const LL mod=1000000007;
LL eular(LL n)
{
LL ret=n,a=n;
for(LL i=2;i*i<=n;i++)
{
if(a%i==0)
ret=ret/i*(i-1);
while(a%i==0)
a/=i;
}
if(a>1)
ret=ret/a*(a-1);
return ret;
}
int main()
{int n,k;
while(cin>>n>>k)
{
if(n==1||k==2)
{cout<<"1"<<endl;continue;}
if(k>2)
{cout<<"0"<<endl;continue;}
LL ans=0;
for(LL i=1;i*i<=n;i++)
if(n%i==0)
{
LL t=eular(i)*eular(n/i)%mod;
(ans+=t)%=mod;
if(i*i!=n)
(ans+=t)%=mod;
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: