欧拉函数小结

来源:互联网 发布:logo制作软件中文版 编辑:程序博客网 时间:2024/06/05 10:16

欧拉函数:小于等于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;}
0 0