我是靠谱客的博主 隐形抽屉,最近开发中收集的这篇文章主要介绍[洛谷 P1891] 疯狂 LCM (欧拉函数 莫比乌斯反演),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题意:

∑ i = 1 n lcm ( i , n ) sum_{i=1} ^{n} text{lcm}(i,n) i=1nlcm(i,n)

分析:

法一:欧拉函数

拆一下 lcm ( i , n ) = i ⋅ n gcd ⁡ ( i , n ) text{lcm}(i,n) = dfrac{i cdot n}{gcd{(i,n)}} lcm(i,n)=gcd(i,n)in 变为:

∑ i = 1 n i ⋅ n gcd ⁡ ( i , n ) sum_{i=1} ^{n} frac{i cdot n}{gcd{(i,n)}} i=1ngcd(i,n)in

枚举 gcd ⁡ ( i , n ) gcd(i,n) gcd(i,n)

n ∑ d ∣ n ∑ i = 1 n i d [ gcd ⁡ ( i , n ) = d ] n sum_{d mid n} sum_{i=1} ^{n} frac{i }{d}[gcd{(i,n)} = d ] ndni=1ndi[gcd(i,n)=d]

利用 gcd ⁡ gcd gcd 的性质:

n ∑ d ∣ n ∑ i = 1 n i d [ gcd ⁡ ( i d , n d ) = 1 ] n sum_{d mid n} sum_{i=1} ^{n} frac{i }{d}[gcd{(frac{i}{d},frac{n}{d})} = 1 ] ndni=1ndi[gcd(di,dn)=1]

d d d 拿到上界

n ∑ d ∣ n ∑ i = 1 ⌊ n d ⌋ i [ gcd ⁡ ( i , n d ) = 1 ] n sum_{d mid n} sum_{i=1} ^{ lfloor frac{n}{d} rfloor } i[gcd{(i,frac{n}{d})} = 1 ] ndni=1dni[gcd(i,dn)=1]

⌊ n d ⌋ lfloor dfrac{n}{d} rfloor dn 等价于 d d d

n ∑ d ∣ n ∑ i = 1 d i [ gcd ⁡ ( i , d ) = 1 ] n sum_{d mid n} sum_{i=1} ^{ d } i[gcd{(i,d)} = 1 ] ndni=1di[gcd(i,d)=1]

由于 gcd ⁡ ( i , d ) = gcd ⁡ ( d − i , d ) gcd(i, d) = gcd(d - i,d) gcd(i,d)=gcd(di,d) ,所以因子必成对出现(除了1),那么总共出现了 φ ( d ) 2 dfrac{varphi(d)}{2} 2φ(d) 次, d − i + i = d d - i + i =d di+i=d,所以就是

n ∑ d ∣ n φ ( d ) 2 d n sum_{d mid n} frac{varphi(d)}{2} d ndn2φ(d)d

这样时间复杂度是 O ( N + T n ) O(N+Tsqrt{n}) O(N+Tn ),但是可以用狄利克雷卷积优化,可以做到 O ( N log ⁡ N + T ) O(N log{N} + T) O(NlogN+T)

F ( x ) = x ⋅ φ ( x ) 2 F(x) = dfrac{x cdot varphi(x)}{2} F(x)=2xφ(x)

则答案为 n ⋅ F ∗ 1 n cdot F * textbf{1} nF1,注意处理 d = 1 d=1 d=1 的情况。

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 5;
int T, n, primes[N], euler[N], cnt, res, f[N];
bool st[N];
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] = 1;
if (i % primes[j] == 0) {
euler[t] = primes[j] * euler[i];
break;
}
euler[t] = (primes[j] - 1) * euler[i];
}
}
for (int i = 1; i <= n; i ++) {
for (int j = i; j <= n; j += i) {
f[j] += (euler[i] * i + 1) / 2;
}
}
}
signed main() {
get_eulers(N - 1);
cin >> T;
while (T --) {
cin >> n;
cout << n * f[n] << endl;
}
}

法二:莫比乌斯反演

还是法一的式子,推到这一步

n ∑ d ∣ n ∑ i = 1 d i [ gcd ⁡ ( i , d ) = 1 ] n sum_{d mid n} sum_{i=1} ^{ d } i[gcd{(i,d)} = 1 ] ndni=1di[gcd(i,d)=1]

用单位函数替换

n ∑ d ∣ n ∑ i = 1 d i ⋅ ε ( gcd ⁡ ( i , d ) ) n sum_{d mid n} sum_{i=1} ^{ d } i cdot varepsilon (gcd{(i,d)}) ndni=1diε(gcd(i,d))

莫比乌斯反演

n ∑ d ∣ n ∑ i = 1 d i ∑ k ∣ gcd ⁡ ( i , d ) μ ( k ) n sum_{d mid n} sum_{i=1} ^{ d } i sum_{k mid gcd(i,d) } mu(k) ndni=1dikgcd(i,d)μ(k)

交换枚举次序

n ∑ d ∣ n ∑ k ∣ d k μ ( k ) ∑ i = 1 ⌊ d k ⌋ i n sum_{d mid n} sum _{k mid d} kmu(k) sum_{i=1} ^{ lfloor frac{d}{k} rfloor } i ndnkdkμ(k)i=1kdi

对后半部分求和

n 2 ∑ d ∣ n ∑ k ∣ d k μ ( k ) ( ⌊ d k ⌋ 2 + ⌊ d k ⌋ ) frac{n}{2} sum_{d mid n} sum _{k mid d} kmu(k) (lfloor frac{d}{k} rfloor ^ 2 + lfloor frac{d}{k} rfloor) 2ndnkdkμ(k)(kd2+kd)

可以用狄利克雷卷积优化到 O ( N log ⁡ N + T ) O(Nlog N +T) O(NlogN+T)

f ( x ) = x ⋅ μ ( x ) f(x)=x cdot mu(x) f(x)=xμ(x) g ( x ) = x 2 + x g(x)=x^2+x g(x)=x2+x F ( x ) = f ∗ g F(x) = f * g F(x)=fg

那么答案就为:

n 2 ⋅ F ∗ 1 frac{n}{2} cdot F * textbf {1} 2nF1

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 5;
int T, n, mobius[N], primes[N], cnt, F[N], ans[N];
bool st[N];
void get_mobius(int n) {
mobius[1] = 1;
for (int i = 2; i <= n; i ++) {
if (!st[i]) {
primes[cnt ++] = i;
mobius[i] = -1;
}
for (int j = 0; primes[j] * i <= n; j ++) {
int t = primes[j] * i;
st[t] = 1;
if (i % primes[j] == 0) {
mobius[t] = 0;
break;
}
mobius[t] = -mobius[i];
}
}
for (int i = 1; i <= n; i ++) {
for (int j = i; j <= n; j += i) {
F[j] += i * mobius[i] * ((j / i) * (j / i) + (j / i));
}
}
for (int i = 1; i <= n; i ++) {
for (int j = i; j <= n; j += i) {
ans[j] += F[i];
}
}
}
signed main() {
get_mobius(N - 1);
cin >> T;
while (T --) {
cin >> n;
cout << n * ans[n] / 2 << endl;
}
}

最后

以上就是隐形抽屉为你收集整理的[洛谷 P1891] 疯狂 LCM (欧拉函数 莫比乌斯反演)的全部内容,希望文章能够帮你解决[洛谷 P1891] 疯狂 LCM (欧拉函数 莫比乌斯反演)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部