Miraclys

一言(ヒトコト)

欧拉函数学习笔记

首先对于欧拉函数\(\varphi(n)\)的定义:小于等于\(n\)的数中,与\(n\)互质的数的个数。
\(\\\)
即:\(\varphi(n)=\sum\limits_{i=1}^{n}[\ \gcd(i,n)=1\ ]\)
\(\\\)
先看几个它的性质
\(\\\)
性质1:
\(\varphi(p)=p-1\)
\(\\\)
性质2:
\(\varphi(p^k) = p^{k} - 1 - (p^{k-1}) = p^{k} - p^{k - 1}\)
我们考虑\(\ p^{k},\ k\in\mathbb{Z},k\ >\ 1\),那么 \(p, 2p, 3p, ... , (p^{k-1}-1)\times p\) 不与\(p\) 互质,又\(p^{k}\)\(p\)为质数,所以没有其它互质的数,所以\(\varphi(p^k) = p^{k} - 1 - (p^{k-1}) = p^{k} - p^{k - 1}\)
\(\\\)
性质3:
\(\varphi(p^{k+1}) = p \times \varphi(p^{k})\)
由性质2得: \(\varphi(p^{k + 1}) = p^{k + 1} - p^{k} \qquad \varphi(p^k) = p^{k} - p^{k-1}\),所以有:\(\varphi(p^{k+1}) = p \times \varphi(p^{k})\)
\(\\\)
性质4:
\(\varphi(p_1^{k_1}p_2^{k_2}) = \varphi(p_1^{k1}) \times \varphi(p_2^{k2})\)
由性质2的思路,考虑与\(p_1^{k_1}\)最大公因数为\(p_1\),即为:\(p_1, 2p_1, 3p_1,..., (p_1^{k_1-1} - 1) \times p_1\)\(p_1^{k_1-1}-1\)
同理,有\(p_2^{k_2 - 1}-1\)个数与 \(p_2^{k_2}\) 最大公因数为\(p_2\)
但是会有重复统计的数,为 \(p_1p_2,2p_1p_2,3p_1p_2,...,(p_1^{k1-1}p_2^{k2-1}-1)p_1p_2\)\((p_1^{k_1-1}p_2^{k_2-1}-1)\)
所以
\(\varphi(p_1^{k_1}p_2^{k_2}) \\ = (p_1^{k_1}p_2^{k_2} - 1) - (p_1^{k_1-1}-1) - (p_2^{k_2 - 1}-1) + (p_1^{k_1-1}p_2^{k_2-1}-1) \\ = (p_1^{k_1} - p_1^{k_1-1})(p_2^{k_2}-p_2^{k_2-1}) \\ = \varphi(p_1^{k_1}) \varphi(p_2^{k_2})\)
\(\\\)
性质5:
\(\varphi(ab) = \varphi(a) \times \varphi(b), \ \gcd(a,b)=1\)
\(\\\)
性质6:
\(n=\prod\limits_{i=1}^{m}p_i^{k_i}\)时,\(\varphi(n)=n\times \prod\limits_{i=1}^m \left( \dfrac{p_i - 1}{p_i}\right)\)
这个式子常用来求解单个\(\varphi(n)\)
\(\\\)
下面利用这些性质,考虑线性求欧拉函数。
根据性质5,有\(\varphi(i \times pri_j) = \varphi(i) \times \varphi(pri_j), \ \gcd(i,pri_j)=1\)
\(\\\)
\(i\)\(phi_j\)不互质时,令\(i \ = \ k \times pri_j^{t}, \ \gcd(k,pri_j)=1\)
此时,有
\(\varphi(i \times pri_j) \\ = \varphi(k\times pri_j \times pri_j^{t}) \\ = \varphi(k \times pri_j^{t+1}) \\ = \varphi(k) \times \varphi(pri_j^{t+1}) \\ = \varphi(k) \times pri_j \times \varphi(pri_j^{t}) \\ = pri_j \times \varphi(i)\)
所以,
\(\varphi(i \times pri_j) = \begin{cases}(pri_j-1) \times \varphi(i)&pri_j \nmid i \\ pri_j \times \varphi(i)&pri_j \mid i \end{cases}\)
那么对于\(i,i\geqslant2\),我们用\(vis\)数组来存储它的最小质因子,顺便也可以当作\(i\)之前是否被筛掉的判断依据。
如果筛到\(i\)\(vis[i]==0\)表明\(i\)为一个质数,则\(\varphi(i)=i-1,\ vis[i]=i\),无论\(i\)是否为质数,都继续枚举目前所筛出的质数,当\(pri_{cur} \times i \geqslant n\)时或者\(pri_{cur} \geqslant vis[i] \ (如果pre_{cur}大于i的最小质因数,则pri_{cur} \times i会在 i 等于\dfrac{i \times pri_{cur}}{vis[i]}时被筛掉)\)时停止。
\(\\\)

#include <bits/stdc++.h>
using namespace std;

const int N = 4e4 + 5;
int n, cnt, vis[N], pri[N], phi[N];

int read() {
	int x = 0, f = 1;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
	return x * f;
}

inline void varphi() {
	phi[1] = 1;
	for (int i = 2; i <= n - 1; ++ i) {
		if (!vis[i]) {
			pri[++cnt] = i;//记录目前所筛出的所有质数 
			phi[i] = i - 1;
			vis[i] = i;
		}
		for (int j = 1; j <= cnt && pri[j] * i <= n - 1 && pri[j] <= vis[i]; ++j) {
			vis[i * pri[j]] = pri[j];//存储的最小质因数 
			if (pri[j] == vis[i]) phi[i * pri[j]] = phi[i] * (pri[j] - 1);//即为线性筛中 此时 i % pri[j]==0 
			else phi[i * pri[j]] = phi[i] * (pri[j]);
		}
	}
}

int main() {
	n = read();
	varphi();
	return 0;
}
posted @ 2022-09-17 16:28  Miraclys  阅读(33)  评论(0编辑  收藏  举报

关于本博客样式

部分创意和图片借鉴了

BNDong

的博客,在此感谢