HDU 1796 容斥

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 25;
long long ans, inp[maxn];
int n, m, t, len;
long long gcd(long long a, long long b)
{
	return b == 0 ? a : gcd(b, a % b);
}
long long LCM(long long a, long long b)
{
	return a * b / gcd(a, b);
}
void dfs(int cur, long long lcm, int id)
{
	lcm = LCM(inp[cur], lcm);
	ans += (id & 1 ? 1 : -1) * (n - 1) / lcm;
	for (int i = cur + 1; i < len; i++)
		dfs(i, lcm, id + 1);
}
int main(int argc, char const *argv[])
{
	while (~scanf("%d%d", &n, &m))
	{
		ans = 0; len = 0;
		while (m--)
		{
			scanf("%d", &t);
			if (t > 0) inp[len++] = t;
		}
		for (int i = 0; i < len; i++)
			dfs(i, inp[i], 1);
		printf("%I64d\n", ans);
	}
	return 0;
}


给定n和一个大小为m的集合,集合元素为非负整数。为1...n内能被集合里任意一个数整除的数字个数。

容斥原理的经典运用,先找出1...n内能被集合中任意一个元素整除的个数,再减去能被集合中任意两个整除的个数,即能被它们两只的最小公倍数整除的个数,因为这部分被计算了两次,然后又加上三个时候的个数,然后又减去四个时候的倍数...所以深搜,最后判断下集合元素的个数为奇还是偶,奇加偶减。

此题使用vector会迷之TLE ,未知原因。

你可能感兴趣的:(HDU 1796 容斥)