数学知识 欧拉函数

欧拉函数

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

欧拉函数的定义
数学知识 欧拉函数_第1张图片
输入格式
第一行包含整数 n

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

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

数据范围
1≤ n ≤ 100,
1≤ ai ≤2×109
输入样例:

3
3
6
8

输出样例:

2
2
4

欧拉函数:求1~n中与n互质的数的个数。
n = p1a1+p2a2+p3a3+p4a4+…pkak
欧拉函数公式: Φ(n)= n * (1-1/p1) * (1-1/p2) * …(1-1/pk)

使用容斥原理证明:
求1~n中与n互质的数的个数的步骤:

  1. 从1~n中去掉 p1 , p2 , p3 ,… pk 的倍数。(因为 p1 的倍数与 n 有共同的约数 p1 ,而pk的倍数有 (n / pk) 个)
  2. 加上所有 pi * pj 的倍数。(因为在1中,删除p1的倍数和p2的倍数的同时将p1和p2的共同的倍数删了两次,重复删除得加回来)
  3. 减去pi * pj * pk 的倍数。(因为在1中,pi * pj * pk的倍数被删除了3次,而在2中,pi * pj * pk倍数被加了三次,所以最后我们要再删一次pi * pj * pk的倍数)
  4. 同上,直到所有 p1 * p2 *… pk的倍数。

上面过程得出的式子为:
n - n/p1 - n/p2 - … n/pk + n/(p1p2) + n/(p1p2)… - n/(p1p2p3)…
上式 = Φ(n)= n * (1-1/p1) * (1-1/p2) * …(1-1/pk)的展开式

代码:

#include
using namespace std;
const int N = 110;
int n;
int main()
{
    cin>>n;
    while(n--)
    {
        int x;
        cin>>x;
        long long int res=x;
        //对每个数分解质因数
        for(int i=2;i<=x/i;i++)
        {
            if(x%i==0)
            {
                res=res*(i-1)/i; // res*(1-1/i) = res * (i-1)/i
                while(x%i==0) x/=i;
            }
        }
        if(x>1) res=res*(x-1)/x;
        
        cout<<res<<endl;
        
    }
    return 0;
}

你可能感兴趣的:(算法,#,数学知识,算法,c++,欧拉函数,容斥原理,数学知识)