CodeForces 839D - Winter is here | Codeforces Round #428 (Div. 2)
赛后听 Forever97 讲的思路,强的一匹- -
/* CodeForces 839D - Winter is here [ 数论,容斥 ] | Codeforces Round #428 (Div. 2) 题意: 给出数列a[N] 对每个子集,若 gcd(a[I1], a[I2], a[I3] ..., a[In]) > 1,则贡献为 n*gcd 求总贡献和 限制: N <= 2e5,a[i] <= 1e6 分析: 记录 num[i]数组为 i 的倍数的个数 则 gcd >= i 能组成的所有方案的总人数 f(i) = 2^(num[i]-1)*num[i] 设 g(i) 为 gcd == i 能组成的所有方案的总人数 可得 f(x) = ∑ [x|y] g(y) 反演或者容斥即可 */ #include <bits/stdc++.h> using namespace std; #define LL long long const int N = 1e6+5; const LL MOD = 1e9+7; int n, a[N], num[N], Max; LL two[N], sum[N]; int main() { two[0] = 1; for (int i = 1; i < N; i++) two[i] = two[i-1] * 2 % MOD; scanf("%d", &n); Max = 0; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); Max = max(a[i], Max); num[a[i]]++; } for (int i = 1; i <= Max; i++) for (int j = i+i; j <= Max; j += i) num[i] += num[j]; LL ans = 0; for (int i = Max; i >= 2; i--) { sum[i] = two[num[i]-1]*num[i] % MOD; for (int j = i+i; j <= Max; j += i) { sum[i] = (sum[i] - sum[j] + MOD) % MOD; } ans = (ans + sum[i] * i % MOD) % MOD; } printf("%lld\n", ans); }
比赛时候写的很随意- -,不过思路是一样的
#include <bits/stdc++.h> using namespace std; #define LL long long const LL MOD = 1e9+7; const int N = 1000005; bool notp[N]; int prime[N], pnum, mu[N]; void Mobius() { memset(notp, 0, sizeof(notp)); mu[1] = 1; for (int i = 2; i < N; i++) { if (!notp[i]) prime[++pnum] = i, mu[i] = -1; for (int j = 1; prime[j]*i < N; j++) { notp[prime[j]*i] = 1; if (i%prime[j] == 0) { mu[prime[j]*i] = 0; break; } mu[prime[j]*i] = -mu[i]; } } } int n, a[N], Max; int num[N]; LL two[N]; int main() { two[0] = 1; for (int i = 1; i < N; i++) two[i] = two[i-1]*2 % MOD; Mobius(); scanf("%d", &n); Max = 0; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); Max = max(Max, a[i]); for (LL j = 1; j*j <= a[i]; j++) { if (j*j == a[i]) num[j]++; else if (a[i] % j == 0) num[j]++, num[a[i]/j]++; } } LL ans = 0; for (int i = 2; i <= Max; i++) { LL sum = 0; for (int j = i, k = 1; j <= Max; j += i, k++) { sum += (mu[k] * (two[num[j]-1]*num[j])%MOD + MOD) % MOD; sum %= MOD; } ans = (ans + sum * i%MOD) % MOD; } printf("%lld\n", ans% MOD); }
我自倾杯,君且随意