HDU 5738 Eureka
题目大意:
给出平面上的 $n$ 个点,每个点有唯一的标号(label),这 $n$ 个标号的集合记作 $S$,点可能重合。求满足下列条件的 $S$ 的子集 $T$ 的数目:
1. $|T|\ge 2$
2. $T$中的点共线
Solution:
只包含一种点的符合条件的子集 $T$ 的数目很容易计算,以下我们只考虑其中至少有两种不同(指坐标不同,下同)点的符合条件的子集$T$(以下简称子集)的数目。
考虑过两不同点 $u, v$ 的直线上的点,将这些点的集合记作 $P_{uv}$,考虑 $P_{uv}$ 的子集对答案的贡献 $C_{u,v}$ 。
设 $|P_{uv}|=k$,则 $C_{uv}=2^k-k-1-\text{single}(P_{uv})$,其中 $\text{single}(P_{uv})$ 指 $P_{uv}$ 的只包含一种点的子集 $T$ 的数目。
现在固定 $u$,计算一共能得到几个 $P_{uv}$。这可通过以 $u$ 为基点,对(去重后的)其他点作极角排序来做到。
以每个点为基点做一次极角排序,这样每个点集 $P_{uv}$ 都被重复计算了 $|P_{uv}|$ 次。
我们用 $f[k]$ 表示模为 $k$ 的点集 $P_k$ 出现的次数。这个次数被重复计算了$k$次,$P_k$出现的次数为$\frac{f[k]}{k}$
则所有$P_k$贡献的子集的数目为
\[\frac{f[k]}{k}(2^k-k-1)-\sum\limits_{P_k}\text{single}(P_k),\]
故总计数为
\[\sum_{k=2}^{n}{\frac{f[k]}{k} 2^k-(k+1)} -\sum_{k=2}^{n}{\sum\limits_{P_k}\text{single}(P_k)}\]
为了计算$\sum_{k=2}^{n}{\sum\limits_{P_k}\text{single}(P_k)}$,另外维护一个数组 $d$,$d[u]$ 表示 $u$ 在多少个点集 $P$ 中出现过。
从而有
\[\sum_{k=2}^{n}{\sum_{P_k}\text{single}(P_k)}=\sum_{u=1}^{m}d[u]*(2^{c[u]}-c[u]-1),\]
其中 $m$ 指去重后的点数,$c[u]$ 表示与 $u$ 重合的点数。
Implement:
#include <bits/stdc++.h>
using namespace std; const int N(1e3+);
typedef long long LL;
LL mod=1e9+; struct point{
LL x, y;
void read(){
scanf("%lld%lld", &x, &y);
}
point operator-(const point &b)const{
return {x-b.x, y-b.y};
}
point operator-(){
return {-x, -y};
}
bool operator==(const point &b)const{
return x==b.x && y==b.y;
}
bool operator<(const point &b)const{
return x==b.x?y<b.y:x<b.x;
}
void out(){
cout<<x<<' '<<y<<endl;
}
LL operator^(const point &p)const{
return x*p.y-y*p.x;
}
}a[N], slope[N]; bool cmp(const int &a, const int &b){
return (slope[a]^slope[b])<; //error-prone
} int cnt[N], b[N], dup[N]; LL num[N], p[N]={}; int main(){ int T, n;
for(int i=; i<=; i++) p[i]=(p[i-]<<)%mod; for(scanf("%d", &T); T--; ){
scanf("%d", &n);
for(int i=; i<n; i++)
a[i].read(); sort(a, a+n);
for(int i=, j=, k=; i<n; j++, k=i){
for(; i<n && a[i]==a[k]; i++);
cnt[j]=i-k;
} int e=unique(a, a+n)-a; memset(num, , sizeof(num));
memset(dup, , sizeof(dup)); for(int i=; i<e; i++){ for(int j=, k=; j<e; j++){
if(i==j) continue;
slope[j]=a[j]-a[i];
if(slope[j].x<) slope[j]=-slope[j];
else if(slope[j].x== && slope[j].y<) slope[j]=-slope[j];
b[k++]=j;
} sort(b, b+e-, cmp); for(int j=, k=, sum; j<e-; k=j){
for(sum=; j<e- && (slope[b[j]]^slope[b[k]])==; sum+=cnt[b[j++]]);
num[sum+cnt[i]]+=cnt[i]; //error-prone
dup[i]++;
}
} LL _dup=, res=; for(int i=; i<e; i++) _dup+=dup[i]*(p[cnt[i]]-cnt[i]-+mod), _dup%=mod;
for(int i=; i<e; i++) res+=p[cnt[i]]-cnt[i]-+mod, res%=mod;
for(int i=; i<=n; i++)
num[i]/=i, res+=num[i]*(p[i]-i-+mod), res%=mod;
res+=mod-_dup, res%=mod;
printf("%lld\n", res);
}
}
UPD
在以某个点为基点进行极角排序需要进行一个将待排序的向量规范化(formalization)的过程, 具体的说就是保证各向量满足:
x>0 或 x==0 && y>0 (待排序都是非零向量)
题解上给出的做法更好一些:
想将输入的点去重后,按照字典序排序, 然后从左到右扫, 当扫到第$i$个点$p_i$时我们统计由$p_i$及其右面的点构成的且一定包含$p_i$的共线子集的数目, 统计的方法和前面类似.
这样做的好处是
1. 向量自然规范化
2. 不重不漏
Implementation:
HDU 5738 Eureka的更多相关文章
- HDU 5738 Eureka 统计共线的子集个数
Eureka 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5738 Description Professor Zhang draws n poin ...
- HDU 5738 Eureka(极角排序)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5738 [题目大意] 给出平面中一些点,在同一直线的点可以划分为一个集合,问可以组成多少包含元素不少 ...
- hdu 5738 Eureka 极角排序+组合数学
Eureka Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- hdu 5738 2016 Multi-University Training Contest 2 Eureka 计数问题(组合数学+STL)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5738 题意:从n(n <= 1000)个点(有重点)中选出m(m > 1)个点(选出的点只 ...
- 2016 Multi-University Training Contest 2题解报告
A - Acperience HDU - 5734 题意: 给你一个加权向量,需要我们找到一个二进制向量和一个比例因子α,使得|W-αB|的平方最小,而B的取值为+1,-1,我们首先可以想到α为输入数 ...
- 2016 Multi-University Training Contest 2 - 1005 Eureka
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5738 题目大意:给定平面上的n个点,一个集合合法当且仅当集合中存在一对点u,v,对于集合中任意点w,均 ...
- HDU 3746:Cyclic Nacklace(KMP循环节)
Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
随机推荐
- centos7下使用yum安装mysql数据库以及设置远程访问
CentOS7的yum源中默认好像是没有mysql的.为了解决这个问题,我们要先下载mysql的repo源. 1. 下载mysql的repo源 $ wget http://repo.mysql.com ...
- 流形学习之等距特征映射(Isomap)
感觉是有很久没有回到博客园,发现自己辛苦写的博客都被别人不加转载的复制粘贴过去真的心塞,不过乐观如我,说明做了一点点东西,不至于太蠢,能帮人最好.回校做毕设,专心研究多流形学习方法,生出了考研的决心. ...
- 基于DDD的.NET开发框架 - ABP启动配置
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 综合使用spring cloud技术实现微服务应用
在之前的章节,我们已经实现了配置服务器.注册服务器.微服务服务端,实现了服务注册与发现.这一章将实现微服务的客户端,以及联调.实现整个spring cloud框架核心应用. 本文属于<7天学会s ...
- Middleware的艺术
定义 Middleware直译叫中间件,目前在百度上很难找到一个简单明了的含义解释,.Net下以前也比较难以看到它的身影,但在Microsoft.Owin里,多个地方都看到MiddleWare,我近来 ...
- TAR命令详解
上图,VPN截图,画蛇添足! 在Linux中,压缩与解压用得最多的tar.tar命令确实很厉害. tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包 ...
- python基础-基本数据类型总结_整型(int)_字符型(str)_day3
一.基本数据类型 1.整型(int) ps1:数字 int ,所有的功能,都放在int里a1 = 123a1 = 456 ps2: int 将字符串转换为数字 # -int # 将字符串转换为数字 ...
- 【Alpha版本】冲刺阶段——Day 7
我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...
- IntelliJ_编译一直报错“找不到符号”
执行maven compile时一直报错"找不到符号",类 XXX 各种clean.compile都不行 最后执行Rebuild Project一次后解决 执行rebuild ...
- editplus-使用正则表达式替换每行首字母和尾字母
打开EditPlus,输入多行数据,快捷键ctrl+h 打开替换窗口,选择“正则表达式”替换 行首批量添加 查找"^" 替换为“我是行首aaa” 行尾批量添加 查找&quo ...