您的位置:首页 > 其它

欧拉函数

2016-03-02 21:25 302 查看
欧拉函数的性质

1、若n是素数p的k次幂,φ(n)=p^k-p^(k-1)=(p-1)p^(k-1),因为除了p的倍数外,其他数都跟n互质

2、欧拉函数是积性函数——若m,n互质,φ(mn)=φ(m)φ(n)

3、当n为奇数时,φ(2n)=φ(n)

4、p是素数,φ(p) = p - 1,φ(p)称为p的欧拉值 φ(1)=1

5、利用这种线性筛法求欧拉函数,需要用到以下几个性质:

若(N%a==0 && (N/a)%a==0) 则有:E(N)=E(N/a)*a;

若(N%a==0 && (N/a)%a!=0) 则有:E(N)=E(N/a)*(a-1);

其中a是N的质因数。

我们通过性质1可以得到求解单个欧拉值的代码

注意那个while(a%i==0)这个循环的作用是 同样的i只能计算一次

比如12==2*2*3

这个2就只能计算一次

我开始看很多博客都没有讲到这个while的作用 想了很久才明白

int solve(int n){
int res=n,a=n;
for(int i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0)
a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}


接下来我们将1-n的筛选

首先O(nlglgn)的算法

void solve(){
euler[1]=1;
for(int i=2;i<Max;i++)
euler[i]=i;
for(int i=2;i<Max;i++)
if(euler[i]==i)
for(int j=i;j<Max;j+=ie)
euler[j]=euler[j]/i*(i-1);
}


这个筛选很简单 可以通过性质1得到

再来一个最终级的代码

O(n)复杂度的

void solve()
{
int i,j;
phi[1]=1;
for(i=2; i<=N; i++) ///相当于分解质因式的逆过程
{
if(!mark[i])
{
prime[++tot]=i;///筛素数的时候首先会判断i是否是素数。
phi[i]=i-1;///当 i 是素数时 phi[i]=i-1
}
for(j=1; j<=tot; j++)
{
if(i*prime[j]>N)  break;
mark[i*prime[j]]=1;///确定i*prime[j]不是素数
if(i%prime[j]==0)///接着我们会看prime[j]是否是i的约数
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else  phi[i*prime[j]]=phi[i]*(prime[j]-1);
///其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性
}
}
}


我们先看这个代码的原理

通过性质4可以得到 !mark[i]可以得出i是素数 于是phi[i]的欧拉值就是i-1就是了

if(!mark[i])
{
prime[++tot]=i;///筛素数的时候首先会判断i是否是素数。
phi[i]=i-1;///当 i 是素数时 phi[i]=i-1
}


我们在看看这段代码

if(i%prime[j]==0)///接着我们会看prime[j]是否是i的约数
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else  phi[i*prime[j]]=phi[i]*(prime[j]-1);


这个是通过性质5得到的

套用一下性质就好了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: