map+组合数学_____Eureka( POJ 5738 2016多校第二场)
2016-08-24 19:57
148 查看
roblem Description
Professor Zhang draws n points
on the plane, which are conveniently labeled by 1,2,...,n.
The i-th point is at (xi,yi).
Professor Zhang wants to know the number of best sets. As the value could be very large, print it modulo 109+7.
A set P (P contains
the label of the points) is called best set if and only if there are at least one best pair in P.
Two numbers u and v (u,v∈P,u≠v) are
called best pair, if for every w∈P, f(u,v)≥g(u,v,w),
where f(u,v)=(xu−xv)2+(yu−yv)2−−−−−−−−−−−−−−−−−−√ and g(u,v,w)=f(u,v)+f(v,w)+f(w,u)2.
Input
There are multiple test cases. The first line of input contains an integer T,
indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤1000) --
then number of points.
Each of the following n lines contains
two integers xi and yi (−109≤xi,yi≤109) --
coordinates of the i-th point.
Output
For each test case, output an integer denoting the answer.
Sample Input
3
3
1 1
1 1
1 1
3
0 0
0 1
1 0
1
0 0
Sample Output
4
3
0
题意:
给定n个平面点,对于一个点集合P,存在一对点u,v.任意w∈P,u,v间的距离≥u,v,w,间距离和的一半。求这样的集合数量。
分析:
化简公式可知,当集合中的所有点共线的时候则集合满足题意。
用最简即约分数表示斜率然后用map存,然后就是组合数学的事情,注意,因为可能有多个点同坐标,所以要特殊处理!!!
代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<map>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
struct node
{
ll x,y;
node(){}
node(ll a,ll b){ x = a, y = b;
}
bool operator < (node b) const
{
if( x == b.x) return y < b.y;
return x < b.x;
}
};
node p[1010];
map<node,ll> mpt;
int n;
ll gcd(ll a,ll b)
{
return b == 0 ? a : gcd(b,a%b);
}
bool cmp(node a, node b)
{
if(a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
ll pow2(ll a,ll b)
{
if( b == 0) return 1;
if( b == 1) return a%mod;
if( b % 2 == 0) return pow2(a*a%mod,b/2);
return pow2(a*a%mod,b/2)*a%mod;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll cnt = 0;
scanf("%d",&n);
for(int i = 0 ; i < n ; i ++)scanf("%lld%lld",&p[i].x,&p[i].y);
sort(p,p+n);
for(int i = 0 ; i < n ; i ++)
{
mpt.clear();
ll step = 0;
for(int j = i + 1 ; j < n ; j ++)
{
if(p[i].x == p[j].x && p[i].y == p[j].y)
{
step ++;
}
else
{
ll tx = p[j].x - p[i].x;
ll ty = p[j].y - p[i].y;
ll g = gcd(tx,ty);
if( g != 0)
{
mpt[node(tx/g,ty/g)] ++;
}
}
}
if(step >= 1) cnt = (pow2(2,step)+cnt-1)%mod;
for(map<node,ll>::iterator it = mpt.begin() ; it != mpt.end() ; it ++)
{
ll k = it->second;
cnt = (cnt + (pow2(2,k)-1)* pow2(2,step))%mod;
}
}
printf("%lld\n",cnt);
}
return 0;
}
Professor Zhang draws n points
on the plane, which are conveniently labeled by 1,2,...,n.
The i-th point is at (xi,yi).
Professor Zhang wants to know the number of best sets. As the value could be very large, print it modulo 109+7.
A set P (P contains
the label of the points) is called best set if and only if there are at least one best pair in P.
Two numbers u and v (u,v∈P,u≠v) are
called best pair, if for every w∈P, f(u,v)≥g(u,v,w),
where f(u,v)=(xu−xv)2+(yu−yv)2−−−−−−−−−−−−−−−−−−√ and g(u,v,w)=f(u,v)+f(v,w)+f(w,u)2.
Input
There are multiple test cases. The first line of input contains an integer T,
indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤1000) --
then number of points.
Each of the following n lines contains
two integers xi and yi (−109≤xi,yi≤109) --
coordinates of the i-th point.
Output
For each test case, output an integer denoting the answer.
Sample Input
3
3
1 1
1 1
1 1
3
0 0
0 1
1 0
1
0 0
Sample Output
4
3
0
题意:
给定n个平面点,对于一个点集合P,存在一对点u,v.任意w∈P,u,v间的距离≥u,v,w,间距离和的一半。求这样的集合数量。
分析:
化简公式可知,当集合中的所有点共线的时候则集合满足题意。
用最简即约分数表示斜率然后用map存,然后就是组合数学的事情,注意,因为可能有多个点同坐标,所以要特殊处理!!!
代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<map>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
struct node
{
ll x,y;
node(){}
node(ll a,ll b){ x = a, y = b;
}
bool operator < (node b) const
{
if( x == b.x) return y < b.y;
return x < b.x;
}
};
node p[1010];
map<node,ll> mpt;
int n;
ll gcd(ll a,ll b)
{
return b == 0 ? a : gcd(b,a%b);
}
bool cmp(node a, node b)
{
if(a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
ll pow2(ll a,ll b)
{
if( b == 0) return 1;
if( b == 1) return a%mod;
if( b % 2 == 0) return pow2(a*a%mod,b/2);
return pow2(a*a%mod,b/2)*a%mod;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll cnt = 0;
scanf("%d",&n);
for(int i = 0 ; i < n ; i ++)scanf("%lld%lld",&p[i].x,&p[i].y);
sort(p,p+n);
for(int i = 0 ; i < n ; i ++)
{
mpt.clear();
ll step = 0;
for(int j = i + 1 ; j < n ; j ++)
{
if(p[i].x == p[j].x && p[i].y == p[j].y)
{
step ++;
}
else
{
ll tx = p[j].x - p[i].x;
ll ty = p[j].y - p[i].y;
ll g = gcd(tx,ty);
if( g != 0)
{
mpt[node(tx/g,ty/g)] ++;
}
}
}
if(step >= 1) cnt = (pow2(2,step)+cnt-1)%mod;
for(map<node,ll>::iterator it = mpt.begin() ; it != mpt.end() ; it ++)
{
ll k = it->second;
cnt = (cnt + (pow2(2,k)-1)* pow2(2,step))%mod;
}
}
printf("%lld\n",cnt);
}
return 0;
}
相关文章推荐
- 2017 杭电多校联赛第二场 1011 Regular polygon(多个点求正方形个数)POJ 2002
- 2016暑假多校合练第二场Multi-University Training Contest 2 1005 Eureka
- (2017多校训练第二场)HDU - 6055 & POJ - 2002 Regular polygon 哈希
- 携程第二场 Poj 1182 食物链(带权并查集) Poj 1948 Triangular Pastures Poj(dp二维背包) 1740 A New Stone Game(博弈)
- Sorting It All Out--POJ 1094
- POJ 1328 Radar Installation
- POJ1088 滑雪 解题报告
- POJ 3164 Command Network
- poj 3660
- POJ 3207 Ikki's Story IV - Panda's Trick(2-SAT判定)
- POJ 3322 Bloxorz I
- POJ1113 Wall
- poj 1556 The Doors
- poj 3436 最大流
- 20140715 「DP - 多重背包」 POJ 1014 Dividing
- poj 2762 Going from u to v or from v to u?(tarjan+拓扑排序)
- POJ 1054 The Troublesome Frog
- POJ 1639 Picnic Planning(初遇最小度限制生成树)
- poj 3041 二分图最大匹配 最小点覆盖
- poj 1328 Radar Installation【贪心】