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 }