题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5738

题目大意:给定平面上的n个点,一个集合合法当且仅当集合中存在一对点u,v,对于集合中任意点w,均有dis(u,v)≥[dis(u,v)+dis(u,w)+dis(v,w)]/2。其中dis(A,B)为A,B两点的欧几里得距离。问你这样的合法集合有多少个。数据范围:1≤n≤1000。

解题思路:对于所给条件简单分析一下就能转化题意,实际上是在求有多少个集合满足集合内的点都在同一直线上。

比赛时的思路一直是,由于可能有重点,于是把重点整合到一个集合里,记一下集合里的个数cnt,那么对于这样一个重点的集合,从中任选至少两个都能作为合法点集,因此对答案的贡献是(2^cnt - cnt - 1)。下面考虑非重点,枚举重点集,对其他重点集按到此点集的距离从小到大排序,再依次枚举,用map记录一下斜率,就能在枚举过程中得到两个重点集之间的点个数K(也就是有多少个点也是这个斜率),对答案的贡献就是(2^cnt1 - 1)*(2^cnt2 - 1)*(2^K)。这样做思路应该没什么问题,只是常数比较大,代码难度也不小。一直到比赛结束也一直WA。

后来看了题解,思路比较清楚。对于这种数方案,要不重不漏的题目要记得使用有序化思想。而在二维坐标中,很常用的两种排序就是x,y双关键字排序,还有极角排序。

首先我们对这n个点做双关键字排序,然后对于x相同的点,个数为cnt,那么对答案的贡献就是(2^cnt - cnt - 1),然后对于每个重点集,对它右面的点做极角排序,做这个排序的意义在于以下就把同一斜率的点搞到了一起,方便计算了。假设当前极角上有p个点那么对答案的贡献就是(2^cnt - 1)*(2^p - 1)。

值得注意的也是十分重要的,就是极角排序的正确做法。首先计算dx, dy,并除掉abs(gcd(dx,dy)),一定要取绝对值!!不然会WA得不明所以!!然后cmp()的时候不要把斜率化成小数比较,直接dyA*dxB<dxA*dyB这样比较可避免精度问题。

总之这道题思想难度不是很大,但是需要的技巧比较多,细节也比较多,是值得一写的题目。

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL; const int MaxN = , Pt = 1e9 + ;
struct Point {
int x, y, dx, dy;
}a[MaxN + ], b[MaxN + ];
int T, n;
LL Pow[MaxN + ];
LL ans; int Gcd(int x, int y)
{
if (y == ) return x;
return Gcd(y, x % y);
} void Init()
{
scanf("%d", &n);
Pow[] = ;
for (int i = ; i <= n; i++) {
scanf("%d%d", &a[i].x, &a[i].y);
Pow[i] = (Pow[i - ] * ) % Pt;
}
} bool cmp(Point A, Point B) {
if (A.x == B.x) return A.y < B.y;
return A.x < B.x;
} bool cmp2(Point A, Point B) {
return (LL)A.dy * B.dx < (LL)A.dx * B.dy;
} void Solve()
{
ans = ;
sort(a + , a + n + , cmp);
int L = , R = ;
while (L <= n) {
while (R < n && a[R + ].x == a[R].x) R++;
//printf("%d %d\n", L, R);
ans = (ans + Pow[R - L + ] - - (R - L + )) % Pt;
int l = L, r = L;
while (l <= R) {
while (r < R && a[r + ].y == a[r].y) r++;
//printf("**%d %d\n", l, r);
int tot = ;
for (int i = R + ; i <= n; i++) {
b[++tot].dx = a[i].x - a[l].x;
b[tot].dy = a[i].y - a[l].y;
int D = Gcd(b[tot].dx, b[tot].dy);
if (D < ) D = -D;
b[tot].dx /= D; b[tot].dy /= D;
}
sort(b + , b + tot + , cmp2);
int cnt = ;
for (int i = ; i <= tot; i++) {
if (i == tot || cmp2(b[i], b[i + ])) {
ans = (ans + (Pow[r - l + ] - ) * (Pow[cnt] - )) % Pt;
cnt = ;
}else cnt++;
}
l = r + ; r = r + ;
}
L = R + ; R = R + ;
}
printf("%I64d\n", ans);
} int main()
{
scanf("%d", &T);
for (int i = ; i <= T; i++) {
Init();
Solve();
}
}

2016 Multi-University Training Contest 2 - 1005 (hdu5738)的更多相关文章

  1. 2016 Al-Baath University Training Camp Contest-1

    2016 Al-Baath University Training Camp Contest-1 A题:http://codeforces.com/gym/101028/problem/A 题意:比赛 ...

  2. hdu 4939 2014 Multi-University Training Contest 7 1005

    Stupid Tower Defense Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  3. 2016 Multi-University Training Contest 2 - 1005 Eureka

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5738 题目大意:给定平面上的n个点,一个集合合法当且仅当集合中存在一对点u,v,对于集合中任意点w,均 ...

  4. 2016 Multi-University Training Contest 4 - 1005 (hdu5768)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5768 题目大意:给你区间[L,R],问你[L, R]中有多少个数字x满足x%7=0且x%p[i]≠a[ ...

  5. 2016 Al-Baath University Training Camp Contest-1 E

    Description ACM-SCPC-2017 is approaching every university is trying to do its best in order to be th ...

  6. 2016 Al-Baath University Training Camp Contest-1 A

    Description Tourist likes competitive programming and he has his own Codeforces account. He particip ...

  7. 2016 Al-Baath University Training Camp Contest-1 J

    Description X is fighting beasts in the forest, in order to have a better chance to survive he's gon ...

  8. 2016 Al-Baath University Training Camp Contest-1 I

    Description It is raining again! Youssef really forgot that there is a chance of rain in March, so h ...

  9. 2016 Al-Baath University Training Camp Contest-1 H

     Description You've possibly heard about 'The Endless River'. However, if not, we are introducing it ...

随机推荐

  1. Luogu P4095 [HEOI2013]Eden 的新背包问题 思维/动规

    当时一直在想前缀和...多亏张队提醒... 从1到n背次包,保存每一个状态下的价值,就是不要把第一维压掉:再从n到1背一次,同样记住每种状态: 然后询问时相当于是max(前缀+后缀),当然前缀后缀中间 ...

  2. P3166 [CQOI2014]数三角形

    传送门 直接求还要考虑各种不合法情况,不好计数 很容易想到容斥 把所有可能减去不合法的情况剩下的就是合法情况 那么我们只要任取不同的三点就是所有可能,不合法情况就是三点共线 对于两点 $(x_1,y_ ...

  3. 2016"百度之星" - 资格赛(Astar Round1)D

    Problem Description 度熊所居住的 D 国,是一个完全尊重人权的国度.以至于这个国家的所有人命名自己的名字都非常奇怪.一个人的名字由若干个字符组成,同样的,这些字符的全排列的结果中的 ...

  4. 提取SQL中用到的表

    dos2unix * for i in `ls` do :}` awk '{print tolower($0)}' "${i}"|grep -Eiw "from" ...

  5. 转——深度学习之BN算法(Batch Normailization)

    Batch Normalization 学习笔记 原文地址:http://blog.csdn.net/hjimce/article/details/50866313 作者:hjimce 一.背景意义 ...

  6. python 元组拾遗

    python 元组拾遗 python 语法糖 def printall(*args):  return args  一个以 * 开头的参数将参数聚集为一个元组. printall函数可以接收任意个数的 ...

  7. java——设计一个支持push,pop,top、在恒定时间内检索最小元素的栈。

    普通方法: 需要另外一个栈 用来存放每一时刻的min值 巧妙版: 只需要一个stack,stack中存的是与min的差值 但由于min是两个整数之间的差值,有可能会出现差值超过整数边界值的情况,因此要 ...

  8. sudo 命令问题详解(一)

    普通用户不能使用sudo命令的解决办法  https://www.cnblogs.com/fasthorse/p/5949946.html 解决sudo: sorry, you must have a ...

  9. apache POI技术的使用

    Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 下载开发包: 解压上面的zip文件: 在项目中引入 ...

  10. jQuery源代码学习笔记_工具函数_noop/error/now/trim

    jQuery源代码学习笔记_工具函数_noop/error/now/trim jquery提供了一系列的工具函数,用于支持其运行,今天主要分析noop/error/now/trim这4个函数: 1.n ...