欧拉函数是指求小于等于正整数n,与n互质的正整数个数。通常用φ(n)表示,例如φ(8)=4,因为小于等于8且与8互质的正整数有1、3、5、7这四个数。欧拉函数在数论和密码学中有广泛的应用
今天我们来求一下每一个正整数的欧拉函数和以及单独正整数的欧拉函数
一:每一个正整数的欧拉函数
给定 n 个正整数 a,请你求出每个数的欧拉函数。
欧拉函数的定义
1∼N 中与 N 互质的数的个数被称为欧拉函数,记为ϕ(N)。
若在算数基本定理中,N=p1a1p2a2…pmam,则:
ϕ(N) = N×p1−1p1×p2−1p2×…×pm−1pm
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个正整数 a。
输出格式
输出共 n 行,每行输出一个正整数 ai 的欧拉函数。
数据范围
1≤n≤100
1≤ai≤2×10^9
输入样例
3
3
6
8
输出样例
2
2
4
类似于容斥原理,一个韦恩图
具体代码如下
#include<iostream>
using namespace std;
int pmi(int x)
{
int res=x;
for(int i=2;i<=x/i;i++)
{
if(x%i==0)
{
res=res/i*(i-1);
while(x%i==0) x/=i;
}
}
if(x>1) res=res/x*(x-1);
return res;
}
int main()
{
int n;
cin>>n;
while(n--)
{
int x;
cin>>x;
int res=pmi(x);
cout<<res<<endl;
}
return 0;
}
二:单独正整数的欧拉函数
利用线性筛来求每一个整数的欧拉函数
不懂线性筛的可以看一下我前面写的博客
思路:
质数i的欧拉函数即为phi[i] = i - 1:1 ~ i−1均与i互质,共i−1个。
phi[primes[j] * i]分为两种情况:
① i % primes[j] == 0时:primes[j]是i的最小质因子,也是primes[j] * i的最小质因子,因此1 - 1 / primes[j]这一项在phi[i]中计算过了,只需将基数NN修正为primes[j]倍,最终结果为phi[i] * primes[j]。
② i % primes[j] != 0:primes[j]不是i的质因子,只是primes[j] * i的最小质因子,因此不仅需要将基数NN修正为primes[j]倍,还需要补上1 - 1 / primes[j]这一项,因此最终结果phi[i] * (primes[j] - 1)。
具体代码如下
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1000010;
int primes[N], cnt;//primes数组存所有的质因子,cnt是下标
int euler[N];//欧拉函数
bool st[N];//表示每个数是否被筛掉了
void get_eulers(int n)
{
euler[1] = 1;
for (int i = 2; i <= n; i ++ )//线性筛
{
if (!st[i])//当前没有被筛过就是质数
{
primes[cnt ++ ] = i;
euler[i] = i - 1;//说明这个数是质数,而质数的欧拉函数为i - 1个
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0)
{
euler[t] = euler[i] * primes[j];
break;
}
euler[t] = euler[i] * (primes[j] - 1);
}
}
}
int main()
{
int n;
cin >> n;
get_eulers(n);
LL res = 0;
for (int i = 1; i <= n; i ++ ) res += euler[i];
cout << res << endl;
return 0;
}
欢迎大家来acwing学算法