2016 Multi-University Training Contest 2 1005 Eureka

题目链接:点击打开链接

题目大意:给你n个点问不在同一直线上的点有多少种取法(至少两个)

解题思路:这题思路其实很明确,但是由于重点的问题很麻烦,最后决定保存重点数量但是不压缩,枚举前两个点,二分找同k的点数;另外对于一条用n个点的直线,他的可能性有2^n-n-1种,但是为了不重复计算,我们只算当前这个点对结果的贡献即(2^n-n-1)-(2^(n-1)-(n-1)-1)=2^(n-1)-1;这样计算就可以处理重复计算情况,时间复杂度大概是n*n*log(n)

代码:

#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<ctime>
#include "cstdio"
#include "string"
#include "string.h"
#include "map"
#include "vector"
using namespace std;
const int mod = 1000000007;
const int maxn = 1010;
struct Node
{
	long long x, y;
	bool friend operator<(Node a,Node b)
	{
		if (a.x == b.x)
			return a.y < b.y;
		else
			return a.x < b.x;
	}
	bool friend operator>(Node a, Node b)
	{
		if (a.x == b.x)
			return a.y > b.y;
		else
			return a.x > b.x;
	}
	bool friend operator==(Node a, Node b)
	{
		return a.x == b.x&&a.y == b.y;
	}
	bool friend operator<=(Node a, Node b)
	{
		return a < b || a == b;
	}
	bool friend operator>=(Node a, Node b)
	{
		return a > b || a == b;
	}
}node[maxn],temp[maxn];
long long pow2[maxn];
map<Node, int>mp;
int now;
bool cmp(Node a, Node b)
{
	Node c = node[now];
	return (b.x - c.x)*(a.y - c.y) < (a.x - c.x)*(b.y - c.y);
}
bool online(Node a, Node b, Node c) {
	long long dx1 = b.x - a.x;
	long long dy1 = b.y - a.y;
	long long dx2 = c.x - a.x;
	long long dy2 = c.y - a.y;
	return dx2 * dy1 == dx1 * dy2;
}
int main()
{
	pow2[0] = 1;
	for (int i = 1;i <= 1000;i++)
		pow2[i] = (pow2[i - 1] * 2) % mod;
	int T, n;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d", &n);
		mp.clear();
		long long ans = 0;
		for (int i = 1;i <= n;i++)
		{
			scanf("%lld %lld", &node[i].x, &node[i].y);
			mp[node[i]]++;
		}
		sort(node + 1, node + n + 1);
		for (int i = 1;i <= n;i++)
		{
			i += mp[node[i]] - 1;
			now = i;
			memcpy(temp, node, sizeof(temp));
			sort(temp + i + 1, temp + n + 1, cmp);
			for (int j = i + 1;j <= n;)
			{
				int k = j + 1;
				if (!online(node[i], temp[j], temp[min(j + 3, n)]))
					while (k <= n&&online(node[i], temp[j], temp[k]))
						k++;
				else
					k = upper_bound(temp + j, temp + n + 1, temp[j], cmp) - temp;
				ans = (ans + (pow2[k - j] - 1)*(pow2[mp[node[i]]]-1)) % mod;
				j = k;
			}
			ans = (ans + pow2[mp[node[i]]] - mp[node[i]] - 1) % mod;
		}
		printf("%lld\n", ans);
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章