题目
[CodeForces 839D] Winter is here
分析
设 m m m 是最大的数,枚举 gcd = d \gcd = d gcd=d,子序列长度为 l l l,要求的就是 ∑ d = 2 m ∑ l = 1 n d ⋅ l ∑ 1 ≤ k 1 < k 2 < ⋯ < k l ≤ n [ gcd i = 1 l a k i = d ] = ∑ d = 2 m ∑ l = 1 n d ⋅ l ∑ 1 ≤ k 1 < k 2 < ⋯ < k l ≤ n ( ∏ i = 1 l [ d ∣ a k i ] ) [ gcd i = 1 l a k i d = 1 ] \begin{aligned} &\sum_{d = 2}^{m}\sum_{l = 1}^{n} d\cdot l \sum_{1 \leq k_1 < k_2 < \cdots < k_l \leq n} \left[\gcd_{i = 1}^l a_{k_i} = d\right] \\ = &\sum_{d = 2}^{m}\sum_{l = 1}^{n} d\cdot l \sum_{1 \leq k_1 < k_2 < \cdots < k_l \leq n} \left(\prod_{i = 1}^{l} [d | a_{k_i}] \right)\left[\gcd_{i = 1}^{l} \frac{a_{k_i}}{d} = 1\right]\end{aligned} =d=2∑ml=1∑nd⋅l1≤k1<k2<⋯<kl≤n∑[i=1gcdlaki=d]d=2∑ml=1∑nd⋅l1≤k1<k2<⋯<kl≤n∑(i=1∏l[d∣aki])[i=1gcdldaki=1] 用莫比乌斯函数的基本性质 μ ∗ 1 = ε \mu * 1 = \varepsilon μ∗1=ε,枚举 a k i d \frac{a_{k_i}}{d} daki 的因数上式转化为: ∑ d = 2 m ∑ l = 1 n d ⋅ l ∑ p = 1 ⌊ m d ⌋ μ ( p ) ∑ 1 ≤ k 1 < k 2 < ⋯ < k l ≤ n ∏ i = 1 l [ ( d ⋅ p ) ∣ a k i ] = ∑ d = 2 m d ∑ p = 1 ⌊ m d ⌋ μ ( p ) ∑ l = 1 n l ∑ 1 ≤ k 1 < k 2 < ⋯ < k l ≤ n ∏ i = 1 l [ ( d ⋅ p ) ∣ a k i ] \begin{aligned} &\sum_{d = 2}^{m}\sum_{l = 1}^{n} d\cdot l\sum_{p = 1}^{\left\lfloor \frac{m}{d} \right\rfloor} \mu(p)\sum_{1 \leq k_1 < k_2 < \cdots < k_l \leq n} \prod_{i = 1}^{l}[(d\cdot p) | a_{k_i}] \\ =&\sum_{d = 2}^{m} d \sum_{p = 1}^{\left\lfloor \frac{m}{d} \right\rfloor} \mu(p) \sum_{l = 1}^{n} l \sum_{1 \leq k_1 < k_2 < \cdots < k_l \leq n} \prod_{i = 1}^{l}[(d\cdot p) | a_{k_i}]\end{aligned} =d=2∑ml=1∑nd⋅lp=1∑⌊dm⌋μ(p)1≤k1<k2<⋯<kl≤n∑i=1∏l[(d⋅p)∣aki]d=2∑mdp=1∑⌊dm⌋μ(p)l=1∑nl1≤k1<k2<⋯<kl≤n∑i=1∏l[(d⋅p)∣aki] 记录原数组中 d ⋅ p d\cdot p d⋅p 倍数的数量 c d ⋅ p c_{d\cdot p} cd⋅p,然后 ∑ l = 1 n l ∑ 1 ≤ k 1 < k 2 < ⋯ < k l ≤ n ∏ i = 1 l [ ( d ⋅ p ) ∣ a k i ] = ∑ l = 1 c d ⋅ p l ( c d ⋅ p l ) \begin{aligned} \sum_{l = 1}^{n} l \sum_{1 \leq k_1 < k_2 < \cdots < k_l \leq n} \prod_{i = 1}^{l}[(d\cdot p) | a_{k_i}] = \sum_{l = 1}^{c_{d \cdot p}} l\binom{c_{d\cdot p}}{l}\end{aligned} l=1∑nl1≤k1<k2<⋯<kl≤n∑i=1∏l[(d⋅p)∣aki]=l=1∑cd⋅pl(lcd⋅p)
令
f
(
n
)
=
∑
i
=
1
n
i
(
n
i
)
f(n) = \sum_{i = 1}^{n} i\binom{n}{i}
f(n)=∑i=1ni(in),由于
(
n
i
)
=
(
n
−
1
i
−
1
)
+
(
n
−
1
i
)
\binom{n}{i} = \binom{n - 1}{i - 1} + \binom{n - 1}{i}
(in)=(i−1n−1)+(in−1),所以
f
(
n
)
=
∑
i
=
1
n
i
(
n
i
)
=
∑
i
=
1
n
i
(
n
−
1
i
−
1
)
+
∑
i
=
1
n
i
(
n
−
1
i
)
=
∑
i
=
0
n
−
1
(
n
−
1
i
)
+
2
f
(
n
−
1
)
=
2
f
(
n
−
1
)
+
2
n
−
1
\begin{aligned}f(n) = &\sum_{i = 1}^{n} i\binom{n}{i} \\ =&\sum_{i = 1}^n i \binom{n - 1}{i - 1} + \sum_{i = 1}^n i\binom{n - 1}{i} \\ =&\sum_{i = 0}^{n - 1}\binom{n - 1}{i} + 2f(n - 1) \\ = &2f(n - 1) + 2^{n - 1}\end{aligned}
f(n)====i=1∑ni(in)i=1∑ni(i−1n−1)+i=1∑ni(in−1)i=0∑n−1(in−1)+2f(n−1)2f(n−1)+2n−1 能够线性递推。
预处理
f
,
c
f, c
f,c 等套式子计算即可,时间复杂度
O
(
m
ln
m
)
O(m \ln m)
O(mlnm)。
代码
#include <bits/stdc++.h>
typedef long long LL;
const int MAXN = 200000;
const int MAXM = 1000000;
const int MOD = 1000000007;
inline int Add(const int &x, const int &y) {
return (x + y >= MOD) ? (x + y - MOD) : (x + y);
}
inline int Mul(const int &x, const int &y) {
return (LL)x * y % MOD;
}
inline int Sub(const int &x, const int &y) {
return (x - y < 0) ? (x - y + MOD) : (x - y);
}
int Pow(int x, int y) {
int ret = 1;
while (y) {
if (y & 1)
ret = Mul(ret, x);
y >>= 1;
x = Mul(x, x);
}
return ret;
}
int N, M;
int A[MAXN + 5];
int Cnt[MAXM + 5], Num[MAXN + 5];
int Mu[MAXM + 5];
bool Vis[MAXM + 5];
std::vector<int> Primes;
void Init(int n) {
Mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (!Vis[i])
Mu[i] = Sub(0, 1), Primes.push_back(i);
for (int j = 0; j < (int)Primes.size() && i * Primes[j] < n; j++) {
Vis[i * Primes[j]] = true;
if (i % Primes[j] == 0) {
Mu[i * Primes[j]] = 0;
break;
}
Mu[i * Primes[j]] = Sub(0, Mu[i]);
}
}
}
int main() {
Init(MAXM);
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
scanf("%d", &A[i]);
Cnt[A[i]]++, M = std::max(M, A[i]);
}
for (int i = 1; i <= M; i++)
for (int j = i + i; j <= M; j += i)
Cnt[i] = Add(Cnt[i], Cnt[j]);
for (int i = 1; i <= N; i++)
Num[i] = Add(Add(Num[i - 1], Num[i - 1]), Pow(2, i - 1));
int Ans = 0;
for (int i = 2; i <= M; i++) {
int cur = 0;
for (int j = 1; j <= M / i; j++)
cur = Add(cur, Mul(Mu[j], Num[Cnt[i * j]]));
Ans = Add(Ans, Mul(i, cur));
}
printf("%d", Ans);
return 0;
}