hdu 5072 Coprime(容斥)
2014-10-29 23:39
387 查看
hdu 5072 Coprime
数学容斥的首杀,借鉴了不少人的博客题意:在一维数组中找出三个数使得两两互质或者两两不互质的方案数。
用总的方案数减去三个数中 至少含有一对互质一对非互质 的情况就是最后答案。
假设a为当前基点,与a至少含有一个公因子的数的个数为B,那么必有(N-1-B)个数与a互质;
为了求出B,显然不能一个个排查,否则会超时。
可以用F[i]表示全局中含有因子i的情况(i的质因子数为g(i)),利用容斥定理进行按j的奇偶性进行累加。其中,i具有一些特殊性:将i分解质因子后所得表达式中每项的指数为1。不然会增加额外的运算时间。
容斥定理按g(i)的奇偶性累加的规则为:
if(g(i)为奇数) +F[i]
else -F[i]
因为 F[ii] = (F[ia] ∩ F[ib] ∩ F[ic]....)|| null 而且 { g(ia)==g(ib)==g(ic)....==g(ii)-1 }
#include <stdio.h> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; #ifdef __GNUC__ typedef long long LL; #define opt64(a) printf("%lld",a); #else typedef __int64 LL; #define opt64(a) printf("%I64d",a); #endif // __GNUC__ const int MAXN = 100000; const double eps = 1e-8; const double PI = acos(-1.0); int prime[MAXN+5], np = 0; int vis[MAXN+5], n, len[MAXN], fac[100]; int aa, ee; vector<int> ls[MAXN]; void divide(int x, int &c) { int k; c = 0; for (int i = 0; i<np; ++i) { k = prime[i]; if (k*k > x) break; if (x % k == 0) { fac[c++] = k; while (x%k==0) x/=k; } } if (x != 1) fac[c++] = x; } void dfs(int x, int dx) { if (dx == ee) { if (x != 1) ls[aa].push_back(x); return; } dfs(x,dx+1); dfs(x*fac[dx], dx+1); } void init_prime() { for (int i = 2; i<= MAXN; ++i) { if (!vis[i]) prime[np++] = i; for (int j = 0; j< np && prime[j]*i <= MAXN; ++j) { vis[prime[j]*i] = 1; if (prime[j] % i == 0) break; } } for (int i = 2; i<= MAXN; ++i) { divide(i, len[i]); aa = i; ee = len[i]; dfs(1,0); } } int cnt[MAXN+5], sf[MAXN+5]; LL solve() { LL res = LL(n)*(n-1)*(n-2)/6; LL ap = 0LL; int as; for (int i = 2; i<= MAXN; ++i) { if (!cnt[i]) continue; for (int j = 0, k=ls[i].size(); j<k; ++j) { sf[ls[i][j]] += cnt[i]; } } for (int i = 2; i<= MAXN; ++i) { if (!cnt[i]) continue; as = 0; for (int j = 0, k=ls[i].size(), c; j<k; ++j) { c = ls[i][j]; if (len[c] & 1) as += sf[c] - 1; else as -= sf[c] - 1; } ap += LL(as)*(n-1-as); } return res - (ap>>1); } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif // ONLINE_JUDGE int t; scanf("%d", &t); init_prime(); while (t--) { scanf("%d", &n); memset(cnt, 0, sizeof cnt); memset(sf, 0, sizeof sf); for (int i = 1; i<= n; ++i) { int num; scanf("%d", &num); ++cnt[num]; } opt64(solve()); puts(""); } return 0; }
相关文章推荐
- hdu 5072 Coprime(同色三角形+容斥)
- HDU 5072 Coprime(同色三角形+容斥)
- HDU 5072 Coprime 2014 Asia AnShan Regional Contest 容斥
- hdu 5072 Coprime (容斥)
- HDU 5072 coprime (同色三角形 + 容斥)
- HDU 5072 Coprime(容斥)
- Hdu 5072 Coprime(容斥)
- hdu 5072 Coprime(同色三角形+容斥)
- hdu 5072 Coprime 2014 Asia AnShan Regional Contest 单色三角形模型+容斥 好题!
- hdu 5072 Coprime 容斥原理
- HDU 5072 - Coprime(容斥原理+素筛)
- HDU 4135 Co-prime (容斥)
- hdu5072 2014 Asia AnShan Regional Contest C Coprime
- hdu 4135 Co-prime 复习容斥
- hdu 4135 Co-Prime 容斥入门
- ACM学习历程—HDU 5072 Coprime(容斥原理)
- hdu 5072 coprime不完整题解
- 【HDU】4135 Co-prime(容斥原理简单应用 质因子的分解)
- HDU 4135 Co-prime(容斥原理求互质数)
- HDU - 1796 How many integers can you find && HDU 4135 Co-prime (容斥)