Codeforces #428 Div2 D
#428 Div2 D
题意
给出一些数,现在要求找出一些数满足 \(i_1 < i_2 < i_3 < ... < i_k\) 以及 \(gcd(a_{i_1}, a_{i_2}, ..., a_{i_k}) > 1\) ,记这些数的贡献为 \(k * gcd(a_{i_1}, a_{i_2}, ..., a_{i_k}) \) 。
求每种方案的贡献之和。
分析
不得不说和 hdu6053 很类似,其实还要简单不少。
考虑枚举 \(gcd\) ,我们可以找到因子有 \(gcd\) 这个数的数有多少个,假设有因子 \(2\) 的数有 \(x\) 个,那么这些数的贡献就是 \(2 * (1*C_{x}^{1}+2*C_{x}^{2}+..+x*C_{x}^{x})\) (通过打表可以发现规律),但是在枚举因子 \(2\) 的时候可能会把 \(2\) 的倍数作为因子形成的方案也考虑了,通过容斥去处理得到最后结果。
这里容斥类似于筛法的思想,实现和理解都更简单。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 10;
const int N = 1e6 + 10;
const int MOD = 1e9 + 7;
ll num[MAXN];
int a[N];
ll has[N];
int main() {
ll e = 1;
for(int i = 1; i < MAXN; i++) {
num[i] = (num[i - 1] * 2 + e) % MOD;
e = e * 2 % MOD;
}
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
int x;
scanf("%d", &x);
a[x]++;
}
ll ans = 0;
for(int i = N - 1; i >= 2; i--) {
int s = 0;
for(int j = i; j < N; j += i) {
s += a[j];
}
has[i] = num[s];
for(int j = 2 * i; j < N; j += i) {
has[i] = (has[i] - has[j] + MOD) % MOD;
}
ans = (ans + 1LL * i * has[i]) % MOD;
}
printf("%I64d\n", ans);
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步