#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 ,未知原因。