[CF839D] Winter is here
Description
给定一个数列 (a_{i}),若子序列长度为 (k),最大公约数为 (gcd),定义子序列的权值为 (k imes 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;
}