题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=5
这个题目一看就是一道数论题,应该考虑使用容斥原理,这里对lcm进行容斥。
不过直接上去是T,考虑到序列中同时存在i和ki的话,其实只需要考虑i,所以先对序列中为倍数的对进行处理。
这里的容斥用了hqw的写法。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <vector> #include <string> #define LL long long using namespace std; const LL maxN = 1e9; int n; int t[60], a[60], len; LL ans; void input() { scanf("%d", &n); len = n; for (int i = 0; i < len; ++i) scanf("%d", &t[i]); for (int i = 0; i < len; ++i) { if (t[i] == -1) continue; for (int j = 0; j < len; ++j) { if (i == j) continue; if (t[j] == -1) continue; if (t[j]%t[i] == 0) t[j] = -1; } } int top = 0; for (int i = 0; i < len; ++i) if (t[i] != -1) a[top++] = t[i]; len = top; sort(a, a+len); } LL gcd(LL x, LL y) { LL r; while (y != 0) { r = y; y = x%y; x = r; } return x; } LL lcm(LL x, LL y) { return x/gcd(x, y)*y; } void dfs(int now, LL num, int sz) { if (now == len) { if (sz) { LL last = maxN/num; if (sz&1) ans -= last; else ans += last; } return; } if (num%a[now] == 0) return; dfs(now+1, num, sz); LL t = lcm(num, a[now]); if (t <= maxN) dfs(now+1, t, sz+1); } void work() { if (len == 1 && a[0] == 1) printf("0 "); else { ans = maxN; dfs(0, 1, 0); cout << ans << endl; } } int main() { //freopen("test.in", "r", stdin); int T; scanf("%d", &T); for (int times = 1; times <= T; ++times) { input(); work(); } return 0; }