[CF839D] Winter is here
Description
给定一个数列 \(a_{i}\),若子序列长度为 \(k\),最大公约数为 \(\gcd\),定义子序列的权值为 \(k \times \gcd\)。求所有 \(\gcd > 1\) 子序列的权值和,答案对 \(10^{9}+7\) 取模。
Solution
枚举 gcd 求贡献
设 \(cnt[i]\) 为 i 出现的次数,\(f[i]\) 为 gcd 为 i 的子序列总长
枚举 i,容斥,先算出 i|gcd 的序列的总长度,然后枚举 i 的每个倍数 j,减去 \(f[j]\),这就要求我们逆序枚举 i
考虑怎么“算出 i|gcd 的序列的总长度”,显然这玩意之和 i|x 的 x 个数有关,为 \(\frac 1 2 c 2^c = c 2^{c-1}\)
证明可用组合推导或平均思想
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5;
const int mod = 1e9 + 7;
int pw2[N];
void presolve_pw2()
{
pw2[0] = 1;
for (int i = 1; i < N; i++)
pw2[i] = pw2[i - 1] * 2 % mod;
}
int n, a[N], f[N];
;
signed main()
{
ios::sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
a[x]++;
}
presolve_pw2();
int ans = 0;
for (int i = N - 1; i > 1; i--)
{
int cnt = 0;
for (int j = i; j < N; j += i)
cnt += a[j];
if (cnt)
{
f[i] = pw2[cnt - 1] * cnt % mod;
for (int j = i + i; j < N; j += i)
f[i] = (f[i] - f[j] + mod) % mod;
ans = (ans + f[i] * i) % mod;
}
}
cout << ans;
}