【POJ 3904】 Sky Code
【题目链接】
http://poj.org/problem?id=3904
【算法】
问题可以转化为求总的四元组个数 - 公约数不为1的四元组个数
总的四元组个数为C(n,4),公约数不为1的四元组个数可以用容斥原理求
【代码】
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; #define MAXN 10010 typedef long long ll; ll i,j,n; ll all,ans; ll a[MAXN]; ll cnt[MAXN]; vector< ll > num[MAXN]; inline ll C(ll n,ll m) { ll i; ll ret = 1; if (n < m) return 0; if (m == 0) return 1; for (i = n; i >= n - m + 1; i--) ret *= i; for (i = 1; i <= m; i++) ret /= i; return ret; } inline void init() { ll i,j,tmp,s; bool flag; for (i = 2; i <= MAXN; i++) { tmp = i; s = 0; flag = false; for (j = 2; j <= sqrt(i); j++) { if (tmp % j == 0) { if (tmp % (j * j) == 0) { flag = true; break; } while (tmp % j == 0) tmp /= j; s++; } } if (tmp > 1) s++; if (!flag) num[s].push_back(i); } } int main() { init(); while (scanf("%lld",&n) != EOF) { all = C(n,4); ans = 0; memset(cnt,0,sizeof(cnt)); for (i = 1; i <= n; i++) scanf("%lld",&a[i]); for (i = 1; i <= n; i++) { for (j = 1; j <= sqrt(a[i]); j++) { if (a[i] % j == 0) { cnt[j]++; if (j * j != a[i]) cnt[a[i]/j]++; } } } for (i = 1; i < MAXN; i++) { for (j = 0; j < num[i].size(); j++) { if (i & 1) ans += C(cnt[num[i][j]],4); else ans -= C(cnt[num[i][j]],4); } } printf("%lld\n",all - ans); } return 0; }