欧拉函数

定义:对于正整数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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值