HDU 5072 Coprime (单色三角形+容斥原理)
题目链接:Coprime
题面:
Coprime
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1181 Accepted Submission(s): 471
Now the Ragnarok is coming. We should choose 3 people to defend the evil. As a group, the 3 people should be able to communicate. They are able to communicate if and only if their id numbers are pairwise coprime or pairwise not coprime. In other words, if their
id numbers are a, b, c, then they can communicate if and only if [(a, b) = (b, c) = (a, c) = 1] or [(a, b) ≠ 1 and (a, c) ≠ 1 and (b, c) ≠ 1], where (x, y) denotes the greatest common divisor of x and y.
We want to know how many 3-people-groups can be chosen from the n people.
For each test case, the first line contains an integer n(3 ≤ n ≤ 105), denoting the number of people. The next line contains n distinct integers a1, a2, . . . , an(1 ≤ ai ≤ 105) separated by
a single space, where ai stands for the id number of the i-th person.
1
5
1 3 9 10 2
4
解题:
题意求找出三数互质或都不互质的组数,直接肯定不行。
此题原型为单色三角形,结果为C(3,n)-res,当中res为每一个与每一个数互质和不互质数量的乘积的累加。求与每一个数不互质的数量,用到了容斥原理。看似简单的原理应用却这么广泛,假设没做过容斥原理的题目,能够先试一下HDU 1796。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
bool status[100010];
int factor[100010][8];
int store[100010],cnt[100010];
long long ans[100010],res;
int one_amount[300];
int refl[300][8];
int cal[8];
void prep()
{
memset(refl,0,sizeof(refl));
int cont=0,temp;
for(int i=0;i<256;i++)
{
temp=i;
one_amount[i]=cont=0;
while(temp)
{
if(temp%2)
{
one_amount[i]++;
refl[i][cont]=1;
}
cont++;
temp/=2;
}
}
}
bool is_prime(int a)
{
if(a<=3)return true;
int x=sqrt(1.0*a);
for(int i=2;i<=x;i++)
{
if(a%i==0)
return false;
}
return true;
}
long long C(int x,int y)
{
long long res=1;
for(int i=1;i<=x;i++)
{
res=res*(y-i+1)/i;
}
return res;
}
int main()
{
int t,n,p,tmp;
long long temp;
scanf("%d",&t);
prep();
while(t--)
{
res=0;
memset(status,0,sizeof(status));
memset(factor,0,sizeof(factor));
memset(cnt,0,sizeof(cnt));
memset(ans,0,sizeof(ans));
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&store[i]);
for(int i=0;i<n;i++)
status[store[i]]=1;
for(int i=2;i<=100000;i++)
{
if(is_prime(i))
{
for(int j=i;j<=100000;j+=i)
{
if(status[j])
{
cnt[i]++;
}
p=0;
while(factor[j][p])
{
p++;
}
factor[j][p]=i;
}
}
else
{
for(int j=i;j<=100000;j+=i)
{
if(status[j])
{
cnt[i]++;
}
} }
}
for(int i=0;i<n;i++)
{
tmp=store[i];
p=0;
while(factor[tmp][p])
{
cal[p]=factor[tmp][p];
p++;
}
if(p==0)
{
ans[i]=0;
continue;
}
tmp=1<<p;
for(int j=1;j<tmp;j++)
{
temp=1;
for(int k=0;k<p;k++)
{
if(refl[j][k])
{
temp=temp*cal[k];
}
}
if(one_amount[j]%2)
ans[i]+=cnt[temp];
else
ans[i]-=cnt[temp];
}
ans[i]-=1;
}
for(int i=0;i<n;i++)
{
res+=(ans[i]*(n-ans[i]-1));
}
res/=2;
printf("%I64d\n",C(3,n)-res);
}
return 0;
}
总结:
用好容斥原理的关键在于,搞清楚集合的交的含义。
HDU 5072 Coprime (单色三角形+容斥原理)的更多相关文章
- hdu 5072 Coprime(同色三角形+容斥)
pid=5072">http://acm.hdu.edu.cn/showproblem.php?pid=5072 单色三角形模型 现场赛和队友想了3个小时,最后发现想跑偏了.感觉好可惜 ...
- HDU 5072 Coprime 同色三角形问题
好吧,我承认就算当时再给我五个小时我也做不出来. 首先解释同色三角形问题: 给出n(n >= 3)个点,这些点中的一些被涂上了红色,剩下的被涂上了黑色.然后将这些点两两相连.于是每三个点都会组成 ...
- hdu 5072 Coprime 容斥原理
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...
- Hdu 5072 Coprime(容斥+同色三角形)
原题链接 题意选出三个数,要求两两互质或是两两不互质.求有多少组这样的三个数. 分析 同色三角形n个点 每两个点连一条边(可以为红色或者黑色),求形成的三条边颜色相同的三角形的个数反面考虑这个问题,只 ...
- ACM学习历程—HDU 5072 Coprime(容斥原理)
Description There are n people standing in a line. Each of them has a unique id number. Now the Ragn ...
- hdu 5072 Coprime
http://acm.hdu.edu.cn/showproblem.php?pid=5072 题意:给出 n 个互不相同的数,求满足以下条件的三元无序组的个数:要么两两互质要么两两不互质. 思路:根据 ...
- hdu 5072 Coprime (容斥)
Problem Description There are n people standing in a line. Each of them has a unique id number. Now ...
- Coprime (单色三角形+莫比乌斯反演(数论容斥))
这道题,先说一下单色三角形吧,推荐一篇noip的论文<国家集训队2003论文集许智磊> 链接:https://wenku.baidu.com/view/e87725c52cc58bd631 ...
- 单色三角形(hdu-5072
单色三角形模型:空间里有n个点,任意三点不共线.每两个点之间都用红色或者黑色线段链接.如果一个三角形的三条边同色,责成这个三角形是单色三角形.对于给定的红色线段列表,找出单色三角形的个数. 分析:对于 ...
随机推荐
- Windows 下 Sublime Text 默认打开方式问题解决办法
Sublime Text 2 是很受ACMer喜爱的文本编辑器 但是绿色版删除后无法设置为默认打开方式...而且网上也没有给出明确的解决办法 注册表的解决办法: 删除 HKEY_CURRENT_USE ...
- CF741DArpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)
题目大意: 给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长 解题思路: 假定给你一个字符串,如何判定其经打乱能否 ...
- C++ 与C# 对应的变量互转
一.C++ 与C# 对应的变量互转的使用实例 C++的动态链接库的函数: C# 调用C++动态链接库数据类型的转换,其中在C++中数据类型为char *,在C#中对应的数据类型为intPtr. 二.常 ...
- spring+mybatis+Atomikos JTA事务配置说明
一.概览 Atomikos是一个公司名字,旗下最著名的莫过于其Atomikos的事务管理器产品.产品分两个:一个是开源的TransactionEssentials,一个是商业的ExtremeTrans ...
- ORA-16009 remote archive log destination must be a STANDBY database
ORA-16009错误处理 问题描述: 主备在做Switchover切换时,在切换后的备库报如下错误: Wed Jul 22 04:49:02 2015 Errors in file /u01/app ...
- 一些常用JS函数和技巧总结
1.JS原生函数parseInt(),返回字符串的第一个数字,默认是十进制. 2.!!data.success //强制转换成布尔类型
- Qt学习 之 Socket通信
近期写大作业用到Qt的Socket部分.网上关于这部分的资料都太过复杂,如今总结一下一些简单的应用.有机会能够给大家讲讲用Socket传送文件的代码. 这里主要解说怎样实现TCP和UDP的简单通信. ...
- oracle_经常使用分组函数
oracle_经常使用分组函数 ①分组函数 1.max(column):求最大值,对数据类型没有要求,随意数据类型都能够 2.min(column):求最小值,对数据类型没有要求,随意数据类型都 ...
- Android 迭代器 Iteraor迭代器以及foreach的使用
Iterator是一个迭代器接口,专门用来迭代各种Collection集合,包括Set集合和List集合. Java要求各种集合都提供一个iteratot()方法,该方法返回一个Iterator用于遍 ...
- Exsi SSH 服务配置
vi /etc/ssh/sshd_conf禁止口令验证PasswordAuthentication no禁止root登录PermitRootLogin no ESXi Shell F2--F2--Tr ...