Winter is here codeforces 839d 容斥

来源:互联网 发布:linux sys.h 编辑:程序博客网 时间:2024/06/05 08:33

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#include <vector>using namespace std;typedef long long ll;const int MAXN = 1000005;const ll mod = 1e9 + 7;ll mypow(ll a, ll b, ll mod) // a ^ b % mod{ll res = 1;while (b > 0){if (b & 1)res = (res * a) % mod;a = (a * a) % mod;b >>= 1;}return res;}ll num[MAXN];ll dp[MAXN];int main(){freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);ios::sync_with_stdio(false);cin.tie(0);int n, val, N;cin >> n;N = 0;while (n--){cin >> val;N = max(N, val);++num[val];int s = sqrt(val);for (int j = 2; j <= s; ++j){if (val % j == 0){++num[j];if (j != val / j)++num[val / j];}}}int ans = 0;for (int i = N; i >= 2; --i){dp[i] = 0;if (num[i] == 0)continue;dp[i] = (ll)num[i] * mypow(2, num[i] - 1, mod) % mod;for (int j = i + i; j <= N; j += i)dp[i] = ((dp[i] - dp[j]) % mod + mod) % mod;ans = (ans + dp[i] * i) % mod;}cout << ans << endl;return 0;}

题意很明显是枚举gcd

设n个数的gcd为g,则这n个数的组合方式有Cnk*g*k(k = 1 .. n)

而Cnk * k(k = 1 ... n) == 2 ^ n - 1

证明:https://www.zybang.com/question/b3f5bf8c82aad7fc37bad7aff826454e.html


对于该组数据

3

2 4 8

其中因子2的个数有3个但有两个来自4和8,则2的组合数量要减去来自4和8的两个2所贡献的组合数量

也就是一个数n他的贡献要减去其倍数2n, 3n, kn的贡献

从后往前计算的话,但计算到n时,2n, 3n的地方都算好的