尤拉函式
我們用$\phi(n)$表示尤拉函式
定義:$\phi(n)$表示對於整數$n$,小於等於$n$中與$n$互質的數的個數
性質
1.$\phi(n)$為積性函式
證明:
此處證明需要用到下面計算方法1中的內容,建議先看後面再回過頭來看這裡
假設存在$p,q$,且$p*q=n$
將$n,p,q$進行質因數分解
$n=a_1^{p_1}*a_2^{p_2}...*a_k^{p_k}$
$p=a_1^{p_1}*a_2^{p_2}...*a_m^{p_m}$
$q=a_{m+1}^{p_{m+1}}*a_{m+2}^{m+2}...*a_k^{p_k}$
那麼
$\varphi \left( n\right) =n\prod ^{k}_{i=1}\left( 1-\dfrac {1}{p_{i}}\right)$
$\varphi \left( a\right) =a\prod ^{m}_{i=1}\left( 1-\dfrac {1}{p_{i}}\right)$
$\varphi \left( b\right) =b\prod ^{k}_{i=m+1}\left( 1-\dfrac {1}{p_{i}}\right)$
因為$n=a*b$
顯然
$\varphi \left( n\right) =\varphi \left( a\right) \varphi \left( b\right)$
這種方法也是常見的證明一個函式是積性函式的方法
2.$\sum_{d|n}\phi(d)=n$
3.$1$到$n$中與$n$互質的數的和為$n*\dfrac{\phi(n)}{2}(n>1)$
證明:若$gcd(n, i) = 1$,那麼$gcd(n, n - i) = 1$
因此與$n$互質的數都是成對出現的。且每一對的和都為$n$
這樣最終答案為$n * \frac{\phi(n)}{2}$
4. $a^{\phi(n)} \equiv 1 \pmod n$
:
計算方法
$\sqrt(n)$計算單值尤拉函式
假設我們需要計算$\phi(n)$
分情況討論
1.當$n=1$時
很明顯,答案為$1$
2.當$n$為質數時
根據素數的定義,答案為$n-1$
(僅有$n$與$n$不互質)
3.當$n$為合數時
我們已經知道了$n$為素數的情況
不妨對$n$進行質因數分解
設$n=a_1^{p_1}*a_2^{p_2}...*a_k^{p_k}$
假設$k=1$
那麼$\phi(p^k)=p^k-p^{k-1}$
證明:
考慮容斥,與一個數互素的數的個數就是這個數減去與它不互素的數的個數
因為$p$是素數,所以在$p^k$中與其不互素的數為$1*p$,$2*p$....$p^{k-1}*p$,有$p^{k-1}$個
得證
當$k\neq 1$時
$$\phi(n)$$
$$=\varphi \left( a^{p_{1}}_{1}a^{p_{2}\ldots }_{2}a^{Pk}_{k}\right)$$
$$=\prod ^{k}_{i=1}a^{P_i}-a^{P_{i}-1}_{i}$$
$$=\prod ^{k}_{i=1}a^{Pi}_{i}(1-\dfrac {1}{p_{i}})$$
$$=n*\prod ^{k}_{i=1}(1-\dfrac {1}{p_{i}})$$
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 1e7 + 10; int p, ans = 1, N; void GetPhi() { for(int i = 2; i * i <= p; i++) { if(p % i == 0) { int now = i - 1; p /= i; while(p % i == 0) now = now * i, p /= i; ans = ans * now; } } if(p != 1) ans *= (p - 1); } int main() { cin >> p; N = p; GetPhi(); cout << ans; return 0; }
線性篩
因為尤拉函式是積性函式
因此可以使用線性篩法
性質1
若$p$為素數,則$\varphi \left( p\right) =p-1$
證明:
在$1-p$中,只有$(p,p)\neq1$
性質2
若$i\ mod\ p \neq 0$,且$p$為素數
則$\varphi \left( i*p\right) =\varphi \left( i\right) *\varphi \left( p\right)$
$=\varphi \left( i\ast p\right) =\varphi \left( i\right) \ast \left( p-1\right)$
這一步同時利用了性質1和尤拉函式的積性
性質3
若$i\ mod \ p = 0$,且$p$為素數,
則$\varphi \left( i\ast p\right) =\varphi \left( i\right) \ast p$
證明:
沒怎麼看懂,丟一個連結
http://blog.csdn.net/Lytning/article/details/24432651
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 10;
void GetPhi(int N) {
static int phi[MAXN], vis[MAXN], prime[MAXN], tot = 0;
for(int i = 2; i <= N; i++) {
if(!vis[i]) prime[++tot] = i, phi[i] = i - 1;
for(int j = 1; j <= tot && i * prime[j] <= N; j++) {
vis[i * prime[j]] = 1;
if(!(i % prime[j])) {phi[i * prime[j]] = phi[i] * prime[j]; break;}
else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
while(cin >> N) cout << phi[N] << endl;
}
int main() {
GetPhi(100);
return 0;
}
例題
放幾道水題
http://poj.org/problem?id=2407
http://poj.org/problem?id=2478
https://www.luogu.org/problemnew/show/P2158
參考資料