当前位置: 代码迷 >> 综合 >> 容斥定理 hdu1796 How many integers can you find
  详细解决方案

容斥定理 hdu1796 How many integers can you find

热度:94   发布时间:2023-12-14 03:57:02.0

因为数据比较小,我的方法非常蠢。。

直接枚举M个数的集合的子集,记为s

然后球子集s里的数的最小公约数,并统计里面的数量,记为cnt

然后看小于n的数中,有多少个最小公约数的倍数,记为t

看cnt的奇偶性,奇数就加t,偶数就减t(容斥定理)


然后就做完了,因为数据小,对于这题复杂度足够了

#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>using namespace std;
typedef long long LL;
typedef pair<int, int> PII;const int MX = 1e2 + 5;LL n;
int S[MX], m;LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;
}LL lcm(LL a, LL b) {return a / gcd(a, b) * b;
}LL solve(LL x) {return (n - 1) / x;
}int main() {//freopen("input.txt", "r", stdin);while(~scanf("%I64d%d", &n, &m)) {int tot = 0, t;for(int i = 0; i < m; i++) {scanf("%d", &t);if(t) S[tot++] = t;}m = tot;LL ans = 0;for(int s = 1; s < (1 << m); s++) {int cnt = 0, sign = false;LL x = 1;for(int i = 0; i < m; i++) {if(s >> i & 1) {x = lcm(x, S[i]);if(x >= n) {sign = true;break;}cnt++;}}if(sign) continue;ans += solve(x) * (cnt % 2 ? 1 : -1);}printf("%I64d\n", ans);}return 0;
}


  相关解决方案