Winter is here codeforces 839d 容斥

本文介绍了一种基于枚举GCD的算法实现,并详细解释了如何通过计算每个数的贡献来解决特定问题。文中提供了完整的C++代码示例,讨论了如何避免重复计算以及如何利用快速幂求解模意义下的运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#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的地方都算好的



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值