关于欧拉函数的理解

碰到一道需要使用欧拉函数打表的题,但是愣是没有发现这是这种题,还是对欧拉函数理解的不够深刻,在这里在对欧拉函数进行一些总结,以备遗忘。

欧拉函数

(1)、这里直接给出欧拉函数的核心式: N=P1^q1*P2^q2*…*Pn^qn。
再给出核心式的变形形式: φ(N)=N*(1-1/P1)(1-1/P2)…*(1-1/Pn)。
再给出欧拉函数的标准数学式(仅了解即可): φ(n)= ∏i=1kφ(prii)= ∏i=1kpri−1×(p−1)= n×∏i=1k(1−1pi) (具体可以去百度百科进行了解) 。此公式是由唯一分解定理+简单的容斥原理得出。唯一分解定理详解

(2)、欧拉函数的实现原理:每次找到一个素因子,之后把它”除干净“,即可保证找的因子全部都为素数(这个比较容易理解,从2开始进行循环,删除二的所有倍数,因为含有倍数,则必定不是素数,从而确保下次循环所选的数必定为素数,额…若仍不理解,可以自己打表看一下,而事实也确实如此)。

(3)、知识点不想过多解释,下面直接给出代码,在代码中进行详解,注意与上文的联系:

//单个数字的欧拉函数
int euler_phi(int n)
{
    int ans=n;//核心式,开头的N
    int m=(int)sqrt(n+0.5);
    for(int i=2;i<=m;i++)//筛选素因子
    {
        if(n%i==0)//若n%i==0则i必为其唯一分解定理中的一项,也就是核心变形式中的一个括号
        {
            ans=ans/i*(i-1);//这里重点注意,可以将此事变形 (i-1)/i * ans,像不像前面所给的核心式的变形形式,然后将这两项看作一项,继续进行下面的乘法,多次循环展开后其实是和上面所给的变形式是一样的。
            while(n%i==0) n/=i;//每次都将素数因子除干净,这样就保证了每次寻找的i均为素数。均在唯一式内
        }
    }
    if(n>1) ans=ans/n*(n-1);//若n不为1,则说明还有素数未除,则是n本身,继续进行上面的操作。
    return ans;//返回总个数。
}




//打印欧拉函数表,上面解释的很详细了,这里简单一提
void phi_table(int n,int *phi)
{
    for(int i=1; i<=n; i++) phi[i]=0;
    phi[1]
    for(int i=2; i<=n; i++)//次循环是判断1-n中所有的素因子
    {
        if(!phi[i])
        {
            for(int j=i; j<=n; j+=i)//注意此处是寻找的此素数的倍数
            {
                if(!phi[j]) phi[j]=j;
                phi[j]=phi[j]/i*(i-1);//这个循环主要是判断此素因子是否在这个数的唯一分解定理中,若在则进行核心变形式的操作
            }
        }
    }
}

关于对欧拉函数的解释,基本就到这里,这里在给出一个链接,是关于,欧拉函数一些边边角角的知识点,在做欧拉函数的题时,可能会遇到,欧拉函数知识点
下面给出一道例题,是一道比较隐晦的欧拉函数的题,但理解后很简单:
https://vjudge.net/problem/UVA-10820

//AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
typedef pair<int,int > P;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAX_N=50001 + 10;
int N,phi[MAX_N];


void phi_table()
{
    memset(phi,0,sizeof(phi));
    phi[1]=1;

    for(int i=2; i<=MAX_N; i++)
    {
        if(!phi[i])
        {
            for(int j=i; j<=MAX_N; j+=i)//注意此处是寻找的此素数的倍数
            {
                if(!phi[j]) phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}



int main()
{
    //ios::sync_with_stdio(false);
    phi_table();
    while(scanf("%d",&N)==1&&N)
    {
        int cnt=0;
        for(int i=2;i<=N;i++) cnt+=phi[i];
        cnt=cnt*2+1;//针对x,y分别来一次,最后加入相同的部分也就是+1
        printf("%d\n",cnt);
    }
    return 0;
}

其余更多关于欧拉函数的例题及其详解
有疑问和不对的地方欢迎在评论区指出,本蒟蒻万分感谢。

猜你喜欢

转载自blog.csdn.net/NCC__dapeng/article/details/81903487