由于斜率的储存精度不够,所以使用最简分数表示记录。
合并同一个位置上的点,然后统计个数,利用公式先求出至少包含2个点的数量。
然后再是求某位之上的点与某一斜率的个数,那就是每边至少一个点的个数相乘。
#include<bits/stdc++.h> using namespace std; const int maxn = 1007; const long long mod = 1e9 + 7; long long powtwo[maxn]; map<pair<int, int>, int>mp; struct node{ int x, y, cnt; bool operator<(const node &a)const{ if(x == a.x) return y < a.y; else return x < a.x; } }a[maxn]; int main(){ powtwo[0] = 1; for(int i = 1; i < maxn; i ++) powtwo[i] = powtwo[i - 1] * 2 % mod; int T, n;scanf("%d",&T);while(T --){ scanf("%d",&n); for(int i = 0; i < n; i ++) scanf("%d%d",&a[i].x, &a[i].y); sort(a, a + n); int i, j, cnt = 0; for(i = 0; i < n;){ for(j = i + 1; j < n; j ++) if((a[i].x != a[j].x) || (a[i].y != a[j].y)) break; a[cnt].x = a[i].x; a[cnt].y = a[i].y; a[cnt ++].cnt = j - i; i = j; } long long ans = 0LL; for(i = 0; i < cnt; i ++) ans = (ans + ((a[i].cnt > 1) ? powtwo[a[i].cnt] - 1 - a[i].cnt : 0)) % mod; for(i = 0; i < cnt; i ++){ mp.clear(); for(j = i + 1; j < cnt; j ++){ int x = a[j].x - a[i].x; int y = a[j].y - a[i].y; int gcd = __gcd(x, y); if(gcd){ x /= gcd; y /= gcd; } mp[make_pair(x, y)] += a[j].cnt; } for(auto it : mp){ ans += (powtwo[a[i].cnt] - 1) * (powtwo[it.second] - 1); ans %= mod; } } printf("%lld ",ans); } return 0; }