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;
}

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