Phi hàm Euler

Hàm số Euler hay phi hàm Euler của một số nguyên dương \(n\) là số lượng số bé hơn hoặc bằng \(n\) và nguyên tố cùng nhau với \(n\). Kí hiệu của hàm số Euler là \(\phi(n)\) (hoặc \(\varphi(n)\)).

Cách tính

Từ định nghĩa, ta có thể tính được \(\phi(p) = p - 1\) và \(\phi(p^k) = p^k - p^{k-1}\) với \(p\) là một số nguyên tố.

  • Đối với \(\phi(p) = p - 1\), ta dễ dàng thấy được rằng với các số \(x\) từ \(1\) đến \(p-1\): \(UCLN(x, p) = 1\).
  • Đối với \(\phi(p^k) = p^k - p^{k-1}\), ta thấy các số \(x\) thoả mãn \(UCLN(x, p) > 1\) chỉ có thể là các số là bội số của \(p\), tức là các số thuộc tập hợp \(\{p, 2p, 3p, \cdots, p^{k-1}p\}\). Vì trong \(p^k\) số từ \(1\) đến \(p\) có \(p^k\) bội số của \(p\) nên ta có \(p^k - p^{k-1}\) số nguyên tố cùng nhau với \(p^k\).

Nếu như ta đã biết giá trị phi hàm Euler của hai số \(a\) và \(b\), ta có thể tính được giá trị \(\phi(ab)\).

  • Nếu \(a, b\) nguyên tố cùng nhau: \[\phi(ab) = \phi(a) \times \phi(b)\]
  • Nếu \(a, b\) không nguyên tố cùng nhau, với \(d = UCLN(a, b)\): \[\phi(ab) = \phi(a) \times \phi(b) \times \frac{d}{\phi(d)}\]

Với các số \(n = p_1^{q_1}p_2^{q_2}\cdots p_k^{q_k}\) với \(p\) là các số nguyên tố, \(q\) là luỹ thừa tương ứng, giá trị của \(\phi(n)\) bằng:

\[\phi(n) = \prod_{i = 1}^{k} p_i^{k_i-1} (p_i - 1)\]

Ví dụ, \(\phi(24) = \phi(2^3 \times 3^1) = 2^2 \times (2 - 1) \times 3^0 \times (3 - 1) = 8\).

Để đưa công thức trên vào chương trình, ta đơn giản hoá công thức để tăng tốc thuật toán. Ta có:

\[ \begin{align} \phi(n) &= \prod_{i = 1}^{k} p_i^{k_i-1} (p_i - 1) \\ &= \prod_{i = 1}^{k} p_i^{k_i} (1 - \frac{1}{p_i}) \\ &= n \times \prod_{i = 1}^{k} (1 - \frac{1}{p_i}) \end{align} \]

Từ đây, ta có công thức tính \(\phi(n)\) bằng:

\[\phi(n) = n \times \prod_{p|n} (1 - \frac{1}{p})\]

Với \(p\) là các ước nguyên tố của \(n\).

int phi(int n){
	int totient = n;
	for(int i = 2; 1ll * i * i <= n; ++i){
		if(n % i == 0){ // i là số nguyên tố
			while(n % i == 0) n /= i;
			totient -= totient / i; // (1 - 1/i)
		}
	}
	if(n != 1) totient -= totient / n;

	return totient;
}

Độ phức tạp của thuật toán bằng \(O(\sqrt{n})\).

Sàng phi hàm Euler

Ta có thể chỉnh sửa thuật toán sàng số nguyên tố để tính giá trị phi hàm Euler của các số từ \(1\) đến \(n\).

int phi[N];

void sievePhi(int n){
    for(int i = 1; i <= n; ++i) phi[i] = i;
    for(int i = 2; i <= n; ++i){
        if(phi[i] == i){ // i là số nguyên tố
            for(int j = i; j <= n; j += i){
               phi[j] -= phi[j] / i; // (1 - 1/i)
            }
        }
    }
}

Vì phi hàm Euler là một hàm nhân tính, ta có thể tính giá trị phi hàm Euler dựa trên công thức \[\phi(n) = n - \sum_{d|n}\phi(d)\]

Với \(d\) là các ước của \(n\) nhỏ hơn \(n\).

int phi[N];

void sievePhi(int n){
    for(int i = 1; i <= n; ++i) phi[i] = i;
    for(int i = 1; i <= n; ++i){
        for(int j = i + i; j <= n; j += i){
           phi[j] -= phi[i];
        }
    }
}

Ứng dụng

Định lí Euler

Phi hàm Euler xuất hiện trong định lí Euler: với hai số \(a\) và \(p\) nguyên tố cùng nhau, ta có: \[a^{\phi(p)} \equiv 1 \pmod p\]

Từ đây, ta dễ dàng tính được giá trị nghịch đảo modulo của \(a\) bằng \(a^{\phi(p)-1} \bmod p\).

Luỹ thừa

Với hai số \(a\) và \(p\) nguyên tố cùng nhau, nếu \(c \equiv d \pmod{\phi(p)}\), thì: \[a^c \equiv a^d \pmod p\]

Tính chất này rất hữu dụng khi ta muốn tính luỹ thừa bậc \(b\) của \(a\) với số mũ \(b\) rất lớn: \[a^b \equiv a^{b \bmod \phi(p)} \pmod p\]