acwing基础课——欧拉函数

由数据范围反推算法复杂度以及算法内容 - AcWing

常用代码模板4——数学知识 - AcWing

基本思想:

这里我们了解一下欧拉函数是什么以及用筛法求欧拉函数,我们先给出欧拉函数的定义:

acwing基础课——欧拉函数_第1张图片 然后我们了解一下互质的概念,只要两数的公因数只有1时,就说这两个数是互质的。 

φ(N)的公式的证明会用到后续学到的容斥原理,这里就直接用容斥原理(思想大致是 在计数时,先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复)来证明

acwing基础课——欧拉函数_第2张图片

acwing基础课——欧拉函数_第3张图片

首先我们减去所有质因子的倍数,然后我们会发先现如果一个数同时是pi和pj的倍数,那么它会被减去两次,所以我们需要加起来,假如一个数是pi,pj,pk的倍数,它先被减去三次,然后加上三次,所以还需要减去一次,依次类推,奇数倍的需要减去,偶数倍的需要加上,这也就是我们的容斥原理的思想,我们将式子整理后就会得到我们的欧拉函数的公式,即证明。

873. 欧拉函数 - AcWing题库

给定 n 个正整数 ai,请你求出每个数的欧拉函数。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个正整数 ai。

输出格式

输出共 n 行,每行输出一个正整数 ai 的欧拉函数。

数据范围

1≤n≤100,
1≤ai≤2×1e9

输入样例:

3
3
6
8

输出样例:

2
2
4
//只要两数的 公因数 只有1时,就说两数是互质数
#include

using namespace std;

int main()
{
    int n;
    cin>>n;
    
    while(n--)
    {
        int x;
        cin >> x;
        
        int res = x;
        
        for(int i = 2; i <= x / i; i++)
        {
            if(x % i == 0)
            {
                res = res / i * (i - 1); // 等价于res = res * (1 - 1 / a)
                while(x % i == 0) x /= i;
            }
        }
        
        if(x > 1) res = res / x * (x - 1);
        
        cout << res << endl;
    }
    
    return 0;
}

筛法求欧拉函数,通过线性筛法来降低我们的时间复杂度,从O(N*根号N)降低到O(N)

acwing基础课——欧拉函数_第4张图片

acwing基础课——欧拉函数_第5张图片

在这里我们先将线性筛法的模版写出,线性筛法在数论中经常会用到,模版要牢记,然后我们来推出欧拉函数公式怎么转化,我们分成三种情况:

第一种,即特殊情况,当一个数i为质数时,那么与他互质的数就是i - 1个;

第二种,当i % pj == 0 时,phi[i] 与phi[pj * i] 只多了一个pj,因为pj是i的质因子,在phi[i]中已经减去了一个1 - 1 / pj,而且欧拉函数的公式中不用考虑质因子的指数,比较一下可以发现phi[pj * i] 比phi[i]多乘了一个pj,所以可以推出phi[pj * i] = pj * phi[i]

第三种,当i % pj != 0 时,因为pj不是i的质因子,在phi[i]中并未减去1 - 1 / pj ,所以此时phi[pj * i]应该等于phi[i] * pj * (1 - 1 / pj) ,即phi[pj * i] = phi[i] * (pj - 1)

874. 筛法求欧拉函数 - AcWing题库

给定一个正整数 n,求 1∼n 中每个数的欧拉函数之和。

输入格式

共一行,包含一个整数 n。

输出格式

共一行,包含一个整数,表示 1∼n 中每个数的欧拉函数之和。

数据范围

1≤n≤1e6

输入样例:

6

输出样例:

12
#include

using namespace std;

typedef long long LL;

const int N = 1000010;

int primes[N], cnt;
int phi[N];
bool st[N];

LL get_eulers(int n)
{
    for(int i = 2; i <= n; i++)
    {
        if(!st[i])
        {
            primes[cnt++] = i;
            phi[i] = i - 1;//特殊情况 当一个数为质数时,那么与他互质的数就是i - 1
        }
        for(int j = 0; primes[j] <= n / i; j++)
        {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0)
            {
                phi[primes[j] * i] = primes[j] * phi[i];
                //第一种情况 当i % pj == 0 
                //phi[i] 与phi[pj * i] 只多了一个pj
                //因为pj是i的质因子,在phi[i]中已经减去了一个1 - 1 / pj
                //而且欧拉函数的公式中不用考虑质因子的指数
                //所以可以推出phi[pj * i] = pj * phi[i]
                break;
            }
            phi[primes[j] * i] = phi[i] * (primes[j] - 1);
            //第二种情况 当i % pj != 0
            //因为pj不是i的质因子
            //在phi[i]中并未减去1 - 1 / pj
            //所以此时phi[pj * i]应该等于phi[i] * pj * (1 - 1 / pj)
            //即phi[pj * i] = phi[i] * (pj - 1)
        }
    }
}

int main()
{
    int n;
    cin >> n;
    
    cout << get_eulers(n);
    
    return 0;
}

你可能感兴趣的:(acwing算法基础课二刷记录,算法,c++,数据结构)