标签:
时限卡的好紧,G++ 3400ms过的,C++超时了。
双关键字排序,然后从左一个一个点看过去,假设第i个点必选,然后对i之后的点按照i这个点为原点进行极角排序,极角相同的排在一起(可以除gcd之后排序),然后统计一下即可。重点需要注意一下。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } const int maxn=1000+10; const LL mod=1e9+7; LL h[maxn]; struct X { LL x,y; } p[maxn],t[maxn]; int T,n,num[maxn]; bool cmp( X a,X b) { if(a.x==b.x) return a.y<b.y; return a.x<b.x; } LL gcd(LL a,LL b) { if(b==0) return a; return gcd(b,a%b); } int main() { h[0]=1; for(int i=1;i<=1000;i++) h[i]=(2*h[i-1])%mod; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lld%lld",&p[i].x,&p[i].y); sort(p,p+n,cmp); p[n].x=p[n].y=(LL)0x7fffffff; for(int i=0;i<n;) { int f=i; for(;;f++) if(p[i].x!=p[f].x||p[i].y!=p[f].y) break; for(int j=i;j<f;j++) num[j]=f-i-(j-i); i=f; } LL ans=0; for(int i=0;i<n;i++) { ans=(ans+h[num[i]-1]-1)%mod; int sz=0; for(int j=i+num[i];j<n;j++) { t[sz].x=p[j].x-p[i].x,t[sz].y=p[j].y-p[i].y; LL GCD=gcd(abs(t[sz].x),abs(t[sz].y)); t[sz].x=t[sz].x/GCD, t[sz].y=t[sz].y/GCD; sz++; } sort(t,t+sz,cmp); t[sz].x=t[sz].y=(LL)0x7FFFFFFF; int cnt=1; for(int j=0;j<sz;j++) { if(t[j].x==t[j+1].x&&t[j].y==t[j+1].y) cnt++; else ans=(ans+h[num[i]-1]*(h[cnt]-1)%mod)%mod,cnt=1; } } printf("%lld\n",ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zufezzt/p/5698056.html