数论
欧拉函数
定义
设\(n\)是一个正整数,欧拉函数\(\phi(n)\)定义为不超过\(n\)且与\(n\)互质的正整数的个数
定理1
设\(p\)和\(q\)是互质的正整数,那么
这个定理说明欧拉函数是一个积性函数,有以下推理
若\(n = p_1^{a_1} \times p_2^{a_2} \times p_3^{a_3} \times ... \times p_k^{a_k}\),其中\(p_1,p_2,p_3...,p_k\)互质,\(a_1,a_2,a_3,...,a_k\)是她们的幂,则\(\phi(n) = \phi(p_1^{a_1}) \times \phi(p_2^{a_2}) \times \phi(p_3^{a_3}) \times ... \times \phi(p_k^{a_k})\)
关于欧拉函数是一个积性函数的证明,读者可以感性理解一下,在这里不给出证明
定理2
设\(n\)为正整数,那么
其中,\(d|n\)表示\(d\)整除\(n\),上式表示对\(n\)的正因数的欧拉函数求和。
这个定理说明了\(n\)与\(\phi(n)\)的关系:\(n\)的正因数(包括1和\(n\)自身)的欧拉函数之和等于\(n\)
证明
\(n\)个分数\(\frac{1}{n},\frac{2}{n},\frac{3}{n},...,\frac{n}{n}\)互不相等。化简这些分数,得到新的\(n\)个分数,她们的分母和分子互质,形如\(\frac{a}{d}\),\(d|n\)且\(a\)与\(d\)互质。在所有\(n\)个分数中,分母为\(d\)的分数的数量为\(\phi(d)\)。所有不同分母的分数,其总数为\(\sum\limits_{d|n}\phi(d)\),所以\(n = \sum\limits_{d|n} \phi(d)\),得证。
定理3
设\(n = p_1 ^ {a_1} \times p_2 ^ {a_2} \times p_3 ^ {a_3} \times ... \times p_k ^ {a_k}\)为正整数\(n\)的质幂因数分解,那么
证明
首先,上述公式有以下两种特殊情况
(1)若\(n\)是质数,\(\phi(n) = n - 1\)。
这一点很容易推理,质数的因数只有\(1\)和她本身。
(2)若\(n = p ^ k\),\(p\)是质数,有\(\phi(n) = \phi(p ^ k) = p ^ k - p ^ {k - 1} = p ^ {k - 1}(p - 1) = p ^ {k - 1} \phi(p)\)。
这一点,我们考虑与\(n\)不互质的数,即因子中含有\(p\)的数,从\(1\)到\(n\)中因子能够含有\(p\)的数有\(p ^ {k - 1}\)个,总共有\(p ^ k\)个数,用总数减掉不互质的数即为欧拉函数。
那么我们如何证明定理3呢
求单个欧拉函数
有了定理3我们就很容易求出单个欧拉函数了,只需要先用试除法分解质因数,再用公式\(\phi(n) = n \prod\limits_{i = 1} ^ k (1 - p_i)\)求得\(\phi(n)\)。时间复杂度为\(O(\sqrt{n})\)
代码
int phi(int n)
{
int ans = n;
for (int i = 2;i * i <= n;i ++)
{
if (n % i == 0)
{
ans = ans / i * (i - 1);//求欧拉函数通式
while(n % i == 0) n /= i;//把这个因数的幂去掉
}
}
if (n != 1) ans = ans / n * (n - 1);//n是质数,n = n - 1
return ans;
}
线性筛求\(1-n\)内的欧拉函数
现在要求\(1-n\)内的所有欧拉函数,前面求单个欧拉函数的复杂度为\(O(\sqrt n)\),如果一个一个求\(1-n\)内所有欧拉函数,那么总复杂度为\(O(n\sqrt n)\),效率太低。
注意到在线性筛的过程中,每一个合数都是被她最小的质因数筛掉。比如设\(p_1\)是\(n\)的最小质因数,\(n' = \frac{n}{p_1}\),那么线性筛的过程中,\(n\)通过\(n' \times p_1\)筛掉。
观察线性筛的过程,我们对\(n' \bmod p_1\)分类讨论
如果\(n' \bmod p_1 = 0\),那么\(n'\)包含了\(n\)的所有质因子。
如果\(n' \bmod p_1 \ne 0\),此时\(n'\)与\(p_1\)互质,根据欧拉函数是积性函数可得
代码
void get_phi()//phi[i]用来储存欧拉函数,vis[i]用来储存最小的质因数,pri[i]用来储存质数
{
phi[1] = 1;//1的欧拉函数是1
for (int i = 2;i <= n;i ++)
{
if (!vis[i])//没有被筛过,i是一个质数
{
vis[i] = i;
pri[++ cnt] = i;
phi[i] = i - 1;//质数的欧拉函数等于该质数减1
}
for (int j = 1;j <= cnt && i * pri[j] <= n;j ++)//枚举已经得到了的质数
{
vis[i * pri[j]] = pri[j];//这个数的最小质因数为第j个质数
if (i % pri[j] == 0)
{
phi[i * pri[j]] = phi[i] * pri[j];//上述的第一种情况
break;
}
phi[i * pri[j]] = phi[i] * phi[pri[j]];//上述的第二种情况
//也可以写作phi[i * pri[j]] = phi[i] * (pri[j] - 1);
}
}
return;
}
求解
考虑\(i <= j\)的情况
对于\(i\)有\(\phi(i)\)个数与\(j\)互质
\(i > j\)的情况
对于\(i\)有\(\phi(i)- 1\)个数可以与\(j\)互质
欧拉定理
设\(m\)是一个正整数,\(a\)是一个整数且\(a\)与\(m\)互质,即\(gcd(a,m) = 1\),则有\(a^{\phi(m)} \equiv 1 \pmod m\)。
莫比乌斯反演
莫比乌斯函数
定义
\(\mu\)为莫比乌斯函数,定义为
详细解释一下:
令\(n = \prod \limits_{i = 1} ^ k p_i ^ {a_i}\),其中\(p_i\)为质因子,\(a_i\)为她的幂,上述定义表示:
1.\(n = 1\)时,\(\mu(n) = 1\)
2.对于\(n \ne 1\)时:
a.当存在\(i\in [1,k]\),使得\(c_i > 1\)时,\(\mu(n) = 0\),也就是说只要某个质因子出现的次数超过一次\(\mu(n)\)就等于0;
b.当任意\(i\in[1,k]\),都有\(c_i = 1\)时,\(\mu(n) = (-1) ^ k\),也就是说每个质因子都仅仅只出现过一次时,即\(n = \prod_{i=1} ^ k p_i\),\(\{p_i\} _ {i=1} ^ k\)中个元素唯一时,\(\mu(n)\)等于 -1 的\(k\)次幂,此处\(k\)指的便是仅仅只出现过一次的质因子的总个数。
性质
莫比乌斯不仅是积性函数,还有以下性质:
即 \(\sum\limits_{d | n} \mu(d) = \varepsilon(n) = [n = 1]\),\(\mu * 1 =\varepsilon\)
证明
设\(n = \prod\limits_{i = 1} ^ k p_i ^ {a_i}\),\(n' = \prod\limits_{i = 1} ^ k p_i\)
那么\(\sum_{d\mid n}\mu(d) = \sum_{d\mid n'}\mu(d)=\sum_{i=0}^k C_k^i \cdot(-1)^i=(1+(-1))^k\)
我们考虑把\(n'\)分解质因数
\(n' = p_1 \times p_2 \times p_3 \times ... \times p_k\)
对于\(\mu(d)\),\(d\)一定是由其中的\(k'\)个因数组成的,所以\(\mu(d) = (-1)^{k'}\)而因数的取法则是从\(p_1\)到\(p_k\)中取\(k'\)个,有\(C_k^{k'}\)种取法,而\(k'\)则是从\(1-k\)中选,因此\(\sum_{d\mid n'}\mu(d)=\sum_{i=0}^k C_k^i \cdot(-1)^i\)
定理
反演定理1:\([gcd(i,j) = 1] = \sum \limits_{d|gcd(i,j)}\mu(d)\)
反演定理2:
\(F(x)\)为\(f(x)\)的和函数,即\(F(x)\)满足\(F(n) = \sum\limits_{d|n} f(d)\)
那么有
线性筛求\(1-n\)内的莫比乌斯函数
void get_mu()
{
mu[1] = 1;
for (int i = 2;i <= n;i ++)
{
if (!vis[i]) pri[++ cnt] = i , mu[i] = -1;//这个数是质数没被标记过
for (int j = 1;j <= cnt && i * pri[j] <= n;j ++)
{
vis[i * pri[j]] = 1;//标记质数
if (i % pri[j] == 0)//如果pri[j]是i的因子,说明i * pri[j]因子中肯定至少含有两个pri[j]
{
mu[i * pri[j]] = 0;
break;
}
mu[i * pri[j]] = -mu[i];//转移
}
}
return;
}
求解
整除分块
对于\(\sum \limits_{i = 1} ^ n f(i)\),\(f(i)\)单调,\(f(i)\)的取值有\(k\)种的某种函数,我们可以做到\(O(k)\)的复杂度
做法:
每次求出\(f(x) = i\)的终点
统计起点与终点之间的值
把\(i\)的终点+1作为下一个值的起点
定理
\(\left\lfloor \dfrac{n}{kd} \right\rfloor\)的取值不会多于\(2 \sqrt {\left\lfloor \dfrac{n}{k} \right\rfloor}\)种
证明
若\(d <= \sqrt {\left\lfloor \dfrac{n}{k} \right\rfloor}\),最多有\(\sqrt {\left\lfloor \dfrac{n}{k} \right\rfloor}\)种取值
若\(d >= \sqrt {\left\lfloor \dfrac{n}{k} \right\rfloor},\left\lfloor \dfrac{n}{kd} \right\rfloor <= \sqrt {\left\lfloor \dfrac{n}{k} \right\rfloor}\),最多有\(\sqrt {\left\lfloor \dfrac{n}{k} \right\rfloor}\)种取值
代码
void solve()
{
int ans = 0;
for (int i = 1;i <= n;i ++) s[i] = s[i - 1] + f[i];
for (int l = 1,r;l <= n;l = r + 1)
{
r = n / (n / l);
ans += s[r] - s[l - 1];
}
return;
}
求解
int solve(int n,int m,int d)
{
int res = 0;
if (n > m) swap(n,m);
n /= d , m /= d;
for (int l = 1,r;l <= n;l = r + 1)
{
r = min(n / (n / l),m / (m / l));
res += (s[r] - s[l - 1]) * (n / l) * (m / l);
}
return res;
}

浙公网安备 33010602011771号