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)个点(选出的点只看标号,不看具体坐标)合成一个集合,问集合中的点共线(可以重合)的集合个数?

思路:按照x,y双关键字排序,之后对每一个点求出所有以它为一个端点的线段个数;

及时计数:要求以当前点为端点的线段数,分成两种情况:

1. 线段就为当前点,即将当前点的重点合成一个点,C(n,2)+C(n,3)+...+C(n,n) = 2n-n-1;

2. 除了包含若干个当前点还有其他点,构成线段;这时对于当前点可取值为2n-1;这时因为其它点是否有重点,对于当前点并没有什么区别;

直接同一斜率的点的个数相加即可(点的个数是指重点缩为一点)细节:不要使用unique来编码。。直接O(n)在线编码好得多;否则还需重载 ==运算符,而目的只是求解出当前节点的重点个数

对于斜率最好使用最简分数的形式保存在map中;

 1 #pragma comment(linker, "/STACK:1024000000,1024000000")
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 #define rep0(i,l,r) for(int i = (l);i < (r);i++)
 5 #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
 6 #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
 7 #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
 8 #define MS0(a) memset(a,0,sizeof(a))
 9 #define MS1(a) memset(a,-1,sizeof(a))
10 #define MSi(a) memset(a,0x3f,sizeof(a))
11 #define inf 0x3f3f3f3f
12 #define lson l, m, rt << 1
13 #define rson m+1, r, rt << 1|1
14 #define A first
15 #define B second
16 #define MK make_pair
17 #define esp 1e-8
18 #define mod 1000000007
19 #define zero(x) (((x)>0?(x):-(x))<eps)
20 #define bitnum(a) __builtin_popcount(a)
21 #define clear0 (0xFFFFFFFE)
22 
23 typedef pair<int,int> PII;
24 typedef long long ll;
25 typedef unsigned long long ull;
26 template<typename T>
27 void read1(T &m)
28 {
29     T x=0,f=1;char ch=getchar();
30     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
31     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
32     m = x*f;
33 }
34 template<typename T>
35 void read2(T &a,T &b){read1(a);read1(b);}
36 template<typename T>
37 void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
38 template<typename T>
39 void out(T a)
40 {
41     if(a>9) out(a/10);
42     putchar(a%10+'0');
43 }
44 inline ll gcd(ll a,ll b){ return b == 0? a: gcd(b,a%b); }
45 struct point2{
46     ll x, y;
47 }p[1007];
48 bool cmp(point2 a,point2 b)
49 {
50     return a.x == b.x ? a.y < b.y: a.x < b.x;
51 }
52 map<PII,int> mp;
53 ll _2[1008];
54 int main()
55 {
56     //freopen("data.txt","r",stdin);
57     //freopen("out.txt","w",stdout);
58     _2[0] = 1;
59     rep1(i,1,1000) _2[i] = (_2[i-1]<<1)%mod;
60     int T, n;
61     cin >> T;
62     while(T--){
63         ll ans = 0;
64         read1(n);
65         rep0(i,0,n) read2(p[i].x, p[i].y);
66         sort(p,p+n,cmp);
67         rep0(i,0,n){
68             int cnt = 1;
69             while(p[i+1].x == p[i].x && p[i+1].y == p[i].y) cnt++,i++; 
70             mp.clear();
71             rep0(j,i+1,n){
72                 ll dy = p[i].y - p[j].y,
73                     dx = p[i].x - p[j].x;
74                 ll g = gcd(dy,dx);
75                 mp[MK(dy/g, dx/g)]++;
76             }
77             ans = (ans + _2[cnt]-cnt-1)% mod;
78             for(auto v = mp.begin(); v != mp.end(); v++){
79                 ans = (ans + (_2[cnt]-1)*(_2[v->second]-1))% mod;
80             }
81         }
82         printf("%lld\n", ans);
83     }
84     return 0;
85 }

 

posted @ 2016-07-24 22:57  hxer  阅读(274)  评论(0编辑  收藏  举报