HDU 5072 容斥原理 + 质因数分解
来源:互联网 发布:java聊天室传文件 编辑:程序博客网 时间:2024/05/22 14:26
HDU 5072
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5072
题意:
给n个数,问有多少对数(a,b,c)使得gcd(a,b)=gcd(b,c)=gcd(a,c)=1,或者gcd(a,b),gcd(b,c),gcd(a,c)均不为1。
思路:
单求为1的倒还好办,因为数字都在1e5以内应该可以用一种质因数分解的方式求出来,但是第二个条件就不好求了。
所以问题转化一下,求tans = 不合法的对数,然后ans = 总数 - tans。
举了几个例子发现,对于每个数求出与他互质的数的个数u,剩下的就是不与他互质的数(n-1-u),则tans = sigma(u*(n-1-u)) / 2。证明的话大概用容斥原理。
然而怎么求与他互质的数的个数……然后就卡死了。
从网上搜解题报告,还是利用容斥原理来求。
对于一个数,质因数分解得到它的质因数数组ele[],然后每个ele最多使用一次能构成的倍数,给这些数的计数器+1,表示此数不与这些数互质。
在求与一个数互质的数dp时,进行同样的质因数分解得到质因数数组ele[],每个ele最多使用一次构成倍数temp。如果ele使用了奇数个,dp+=num[temp](num是计数器,temp表示这个倍数),否则dp-=num[temp]。具体可以用全概率公式的原理来解释。
源码:
#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>#include <string>using namespace std;#define LL long longconst int MAXN = 200000 + 5;int vis[MAXN];int g[MAXN];int num[MAXN];int p[MAXN], cnt;int data[MAXN];void init(){ memset(vis, 0, sizeof(vis)); cnt = 0; for(int i = 2 ; i < MAXN ; i++){ if(vis[i] == 0){ p[cnt++] = i; int u = i; while(u < MAXN) vis[u] = 1, u += i; } }}int ele[MAXN];int main(){// freopen("C.in", "r", stdin); init(); int t; scanf("%d", &t); while(t--){ int n; scanf("%d", &n); memset(g, 0, sizeof(g)); for(int i = 0 ; i < n ; i++) scanf("%d", &data[i]), g[data[i]] = 1; memset(num, 0, sizeof(num)); for(int i = 0 ; i < n ; i++){ cnt = 0; int temp = data[i]; for(int j = 0 ; p[j] * p[j] <= temp ; j++){ if(temp % p[j] == 0){ ele[cnt++] = p[j];// printf("cnt = %d, p[j] = %d, temp = %d\n", cnt, p[j], temp); while(temp % p[j] == 0){ temp /= p[j];// printf("temp = %d, p[j] = %d\n", temp, p[j]); } } } if(temp != 1) ele[cnt++] = temp; for(int j = 0 ; j < (1 << cnt) ; j++){ int which = 1; for(int k = 0 ; k < cnt ; k ++){ if((1 << k) & j) which *= ele[k]; } num[which]++; } }// printf("second\n"); LL ans = 0; for(int i = 0 ; i < n ; i++){ cnt = 0; int temp = data[i]; for(int j = 0 ; p[j] * p[j] <= temp ; j++){ if(temp % p[j] == 0){ ele[cnt++] = p[j]; while(temp % p[j] == 0) temp /= p[j]; } } if(temp != 1) ele[cnt++] = temp; LL tans = 0; for(int j = 1 ; j < (1 << cnt) ; j++){ int sta = 0; LL which = 1; for(int k = 0 ; k < cnt ; k++){ if((1 << k) & j){ sta++, which *= ele[k]; } } if(which > MAXN) continue; if(sta & 1) tans += num[which]; else tans -= num[which]; } if(tans > 0) tans--; ans += tans * (n - 1 - tans); } ans = (LL)n * (n - 1) * (n - 2) / 6 - ans / 2; printf("%I64d\n", ans); } return 0;}
0 0
- HDU 5072 容斥原理 + 质因数分解
- HDU 4135 Co-prime (容斥原理+质因数分解)
- HDU 1695 GCD (容斥原理+质因数分解)
- HDU 4407 Sum(容斥原理+质因数分解)
- HDU 4135 Co-prime (容斥原理/分解质因数)
- HDU 4135 Co-prime(容斥原理+分解质因数)
- 容斥原理+质因数分解+组合数学
- poj 3904 容斥原理+质因数分解
- 容斥原理+质因数分解-HDU4135
- 周赛 1007 题解 hdu 4390 Number Sequence (质因数分解+组合数学+容斥原理)
- HDU 1695 GCD 欧拉函数+容斥原理+质因数分解
- Ural 1091. Tmutarakan Exams 排列组合+容斥原理+质因数分解
- GCD and LCM 质因数分解与容斥原理
- 【HDU5072】Coprime-补集转化+容斥原理+质因数分解
- hdu4407(容斥原理+分解质因数)Sum
- hdu2841(容斥原理+分解质因数)Visible Trees
- HDU 4135 Co-prime (分解质因数 + 容斥)
- hdu 2841 Visible Trees 容斥,分解质因数
- HDU 5113 DFS + 剪枝
- hdu 4770 Lights Against Dudely(二进制枚举情况)
- 构建需求响应式亿级商品详情页
- 技能系统设计笔记 4
- Redis运行流程源码解析
- HDU 5072 容斥原理 + 质因数分解
- 技能系统设计笔记 5
- 回归诊断的r语言代码
- bootloader概述
- HDU 5073 思维
- 技能系统设计笔记 6
- 被问到的面试题
- 关于背景色颜色重置
- HDU 5112 水