欧拉函数+证明+其函数应用

原网址:https://blog.csdn.net/Danliwoo/article/details/48827813#fermat

 

。。看不懂目前也不想去钻研,,

索性粘贴上看过的内容,留着用

void genPhi()
{
    for(int i = 1;i < max;i++)
        minDiv[i] = i;
    for(int i = 2;i*i < max;i++)
    {
        if(minDiv[i] == i)
        {
            for(int j = i*i;j < max;j += i)
                minDiv[j] = i;
        }
    }
    phi[1] = 1;
    for(int i = 2;i < max;i++)
    {
        phi[i] = phi[i/minDiv[i]];
        if((i/minDiv[i]) % minDiv[i] == 0)
            phi[i] *= minDiv[i];
        else
            phi[i] *= minDiv[i] - 1;
    }
}

资料来源:https://blog.csdn.net/Danliwoo/article/details/48851073

真心看不明白,,又觉得讲得很好的样子。。

欧拉函数的证明以及应用(附POJ例题)


应用

POJ 2407

给n,求ϕ(n)ϕ(n) 
按照欧拉函数公式分解出所有n的质因子即可计算得到答案。复杂度O(n−−√n)

int phi(int n)
{
    int ans = n;
    for(int i = 2;i*i <= n;i++)if(n % i == 0)
    {
        ans -= ans/i;
        while(n % i == 0)
            n /= i;
    }
    if(n != 1)
        ans -= ans/n;
    return ans;
}

POJ 1284

给素数p,求原根,即ϕ(p−1)ϕ(p−1) 
关于原根的知识之后再补充。

POJ 2478

给n,求ans[n]。其中ans[n]=ans[n-1]+phi[n],且n的范围比较大,在10的6次以内。则考虑打表解决。 
先得到能整除i的最小正整数md[i](一定是个素数),再利用性质3,得到phi[i]

void set()
{
    for(int i = 0;i < N;i++)
        md[i] = i;
    for(int i = 2;i < N;i++)  if(md[i] == i)
    {   //也可以只让2和奇数进来
        for(int j = i;j < N;j += i)  if(md[j] == j)
            md[j] = i;  //只要最小的,不要被覆盖
    }
    for(int i = 2;i < N;i++)
    {
        if(md[i] == i)
            phi[i] = i-1;
        else
        {
            phi[i] = phi[i/md[i]];
            if(i/md[i] % md[i])
                phi[i] *= md[i]-1;
            else
                phi[i] *= md[i];
        }
    }
}

后面这种写法比较简短,也可以根据性质3来理解。

void set()
{
    for(int i = 0;i < N;i++)
        phi[i] = i;
    for(int i = 2;i < N;i += 2)
        phi[i] /= 2;  //质数为2先处理一遍
    for(int i = 3;i < N;i += 2) if(phi[i] == i)
    {  //处理奇因子
        for(int j = i;j < N;j += i)
            phi[j] = phi[j]/i*(i-1);
    }
}

POJ 3090

给n,求ans[i] = ans[i-1] + 2*phi[i]

猜你喜欢

转载自blog.csdn.net/sodacoco/article/details/81515891