欧拉函数
公式求欧拉函数
- 证明:容斥原理
- 首先N减去所有其质因子的倍数
- 减完后会发现两个质因子乘积的倍数被多减去了,再加回来
- 加回来后会发现三个质因子乘积的倍数被多加上了,再减回去
- 就这样子一直下去就得到了上面的公式
- C++
int phi(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;
}
线性筛法求欧拉函数
在线性筛法筛质数中,一共有三种情况
-
在遍历时直接遍历到了这个数
i,这个数就是一个质数这个数的欧拉函数为
euler[i] = i - 1 -
将这个质数
i和之前确定的质数primes[j]的乘积t筛掉此时
t的欧拉函数为euler[t] = primes[j] * euler[i] * ((primes[j] - 1) / primes[j])即euler[t] = euler[i] * (primes[j] - 1) -
当
i % primes[j] == 0时,此时primes[j]是i的最小质因数此时
t的欧拉函数为euler[t] = primes[j] * euler[i]
- C++
int primes[N], cnt; // primes[]存储所有素数
int euler[N]; // 存储每个数的欧拉函数
bool st[N]; // st[x]存储x是否被筛掉
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;
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) //此时primes[j]是i的最小质因数
{
euler[t] = euler[i] * primes[j];
break;
}
euler[t] = euler[i] * (primes[j] - 1);
}
}
}
练习
01 欧拉函数
- 题目
- 题解
import java.io.*;
import java.util.*;
public class Main {
public static int n;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
n = Integer.parseInt(br.readLine());
while (n-- > 0) {
pw.println(phi(Integer.parseInt(br.readLine())));
}
pw.close();
br.close();
}
public static int phi(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;
}
}
02 筛法求欧拉函数
- 题目
- 题解
import java.io.*;
import java.util.*;
public class Main {
public static final int N = 1000010;
public static int[] euler = new int[N]; //存i的欧拉函数
public static boolean[] st = new boolean[N]; //存i是否被筛过
public static int[] primes = new int[N]; //存所有素数
public static int idx, n;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
n = Integer.parseInt(br.readLine());
getEulers(n);
long res = 0;
for (int i = 1; i <= n; i++) {
res += euler[i];
}
pw.println(res);
pw.close();
br.close();
}
public static void getEulers(int n) {
euler[1] = 1;
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[idx++] = i;
euler[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j++) {
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) { //此时primes[j]是i的最小质因数
euler[t] = primes[j] * euler[i];
break;
}
euler[t] = euler[i] * (primes[j] - 1);
}
}
}
}