題目鏈接:點擊打開鏈接
題目大意:給你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;
}