牛客挑战赛47 F-简单题 莫比乌斯反演
传送门: https://ac.nowcoder.com/acm/contest/10743/F
题意
求 解 ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) μ ( i j ) φ ( i j ) 求解\sum_{i=1}^n\sum_{j=1}^mgcd(i,j)\mu(ij)\varphi (ij) 求解i=1∑nj=1∑mgcd(i,j)μ(ij)φ(ij)
思路
根
据
积
性
函
数
和
μ
的
性
质
,
只
有
i
和
j
互
质
时
才
有
贡
献
,
不
然
μ
(
i
j
)
=
0
\red{根据积性函数和\mu的性质,只有i和j互质时才有贡献,不然\mu(ij)=0}
根据积性函数和μ的性质,只有i和j互质时才有贡献,不然μ(ij)=0
i
和
j
互
质
时
,
φ
(
i
j
)
=
φ
(
i
)
φ
(
j
)
μ
(
i
j
)
=
μ
(
i
)
μ
(
j
)
g
c
d
(
i
,
j
)
=
1
\red{i和j互质时,\varphi (ij)=\varphi (i)\varphi (j)\;\;\mu(ij)=\mu(i)\mu(j)\;\;gcd(i,j)=1}
i和j互质时,φ(ij)=φ(i)φ(j)μ(ij)=μ(i)μ(j)gcd(i,j)=1
根 据 上 述 可 得 : 根据上述可得: 根据上述可得:
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
1
]
φ
(
i
)
μ
(
i
)
φ
(
j
)
μ
(
j
)
\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]\varphi (i)\mu(i)\varphi (j)\mu(j)
i=1∑nj=1∑m[gcd(i,j)=1]φ(i)μ(i)φ(j)μ(j)
设
f
(
i
)
=
φ
(
i
)
∗
μ
(
i
)
,
g
(
j
)
=
φ
(
j
)
∗
μ
(
j
)
,
则
设f(i)=\varphi (i)*\mu(i),g(j)=\varphi (j)*\mu(j),则
设f(i)=φ(i)∗μ(i),g(j)=φ(j)∗μ(j),则
∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] f ( i ) g ( j ) \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]f(i)g(j) i=1∑nj=1∑m[gcd(i,j)=1]f(i)g(j)
∑ i = 1 n ∑ j = 1 m f ( i ) g ( j ) ∑ d ∣ i d ∣ j μ ( d ) \sum_{i=1}^n\sum_{j=1}^mf(i)g(j)\sum_{d|i\;d|j}\mu(d) i=1∑nj=1∑mf(i)g(j)d∣id∣j∑μ(d)
交 换 枚 举 顺 序 : 交换枚举顺序: 交换枚举顺序:
∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 n f ( i ) [ d ∣ i ] ∑ j = 1 m g ( j ) [ d ∣ j ] \sum_{d=1}^{min(n,m)}\mu(d)\sum_{i=1}^nf(i)[d|i]\sum_{j=1}^mg(j)[d|j] d=1∑min(n,m)μ(d)i=1∑nf(i)[d∣i]j=1∑mg(j)[d∣j]
根 据 上 式 , 可 以 预 处 理 φ , μ , f , g 函 数 。 然 后 暴 力 求 解 , 即 : 根据上式,可以预处理\varphi,\mu,f,g函数。然后暴力求解,即: 根据上式,可以预处理φ,μ,f,g函数。然后暴力求解,即:
int n, m; cin >> n >> m;
for(int i = 1;i <= n; i++) f[i] = phi[i];
for(int j = 1;j <= m; j++) g[j] = phi[j];
ll ans = 0;
for(int d = 1;d <= min(n, m); d++) {
if(!mu[d]) continue;
ll sum1 = 0, sum2 = 0;
for(int i = d;i <= n; i += d) sum1 += f[i];
for(int j = d;j <= m; j += d) sum2 += g[j];
ans = (ans + sum1 * sum2 * mu[d]) ;
}
但 是 这 样 会 T 掉 , 因 为 d = 1 时 , n 过 大 , 那 复 杂 度 就 是 O ( n 2 ) 了 。 但是这样会T掉,因为d=1时,n过大,那复杂度就是O(n^2)了。 但是这样会T掉,因为d=1时,n过大,那复杂度就是O(n2)了。
需 要 D i r i c h l e t 前 缀 和 优 化 即 可 。 这 是 前 缀 和 的 几 个 版 本 : 需要Dirichlet 前缀和优化即可。这是前缀和的几个版本: 需要Dirichlet前缀和优化即可。这是前缀和的几个版本:Dirichlet 前缀和
D i r i c h l e t 前 缀 和 优 化 之 后 的 复 杂 度 为 O ( n log log n ) , 完 全 可 以 接 受 。 Dirichlet 前缀和优化之后的复杂度为O(n\log \log n),完全可以接受。 Dirichlet前缀和优化之后的复杂度为O(nloglogn),完全可以接受。
Code(2512 MS)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = (1ll << 32);
const int N = 2e7 + 10;
int cnt;
int prime[N];
bool is_prime[N];
int mu[N];
int phi[N];
void init() {
phi[1] = mu[1] = is_prime[0] = is_prime[1] = 1;
for(int i = 2;i < N; i++) {
if(!is_prime[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
mu[i] = -1;
}
for(int j = 1;j <= cnt && prime[j] * i < N; j++) {
is_prime[i * prime[j]] = 1;
if(i % prime[j] == 0) {
mu[i * prime[j]] = 0;
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i < N; i++) phi[i] *= mu[i];
}
int f[N], g[N];
void solve() {
int _; cin >> _;
init();
while(_--) {
int n, m; cin >> n >> m;
for(int i = 1;i <= n; i++) f[i] = phi[i];
for(int j = 1;j <= m; j++) g[j] = phi[j];
ll ans = 0;
for(int i = 1;i <= cnt; i++) {
for(int j = n / prime[i];j >= 1; j--) f[j] += f[j * prime[i]];
for(int j = m / prime[i];j >= 1; j--) g[j] += g[j * prime[i]];
}
for(int i = 1;i <= min(n, m); i++) {
ans += 1ll * f[i] * g[i] * mu[i] % mod;
ans %= mod;
}
cout << (ans + mod) % mod << endl;
}
}
signed main() {
solve();
return 0;
}