【2020.05.30省選模擬】6674. 凸包的價值

題目

Description

在這裏插入圖片描述
在這裏插入圖片描述
Input
在這裏插入圖片描述

Output
在這裏插入圖片描述

Sample Input
4
2 5 3
1 0
3 3
1 3
2 2

Sample Output
336

【樣例 2 解釋】
樣例二滿足 n<=19。

Data Constraint
在這裏插入圖片描述
在這裏插入圖片描述

思路

首先在這裏插入圖片描述
然後我們可以考慮凸包的組合意義
我們可以認爲每一個點有b種狀態,其中a種是 0,c 種是 1。求所有方案 的點構成的凸包的邊數和。
那麼我們可以枚舉一條邊。這條邊對答案有貢獻當且僅當它一側的點全都是0,這條邊上的點隨便,另一側至少有一個1 。那麼就直接計算就好了。

思路

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4077,mod=1e9+7;
const double e=1e-12;
int n;
ll a,b,c,_b[N],_c[N],ans;
struct P
{
	ll x,y;
	double t;
	P(){}
	P(ll _x,ll _y){x=_x,y=_y,t=atan2(_y,_x);}
	P operator-(const P&a)const{return P(x-a.x,y-a.y);}
	ll operator*(const P&a)const{return x*a.y-y*a.x;}
	bool operator<(const P&a)const{return t<a.t-e||fabs(t-a.t)<e&&abs(x)+abs(y)>abs(a.x)+abs(a.y);}
}p[N],A[N];
int add(int x)
{
	return x%(n-1)+1;
}
int main()
{
	freopen("value.in","r",stdin); freopen("value.out","w",stdout);
	scanf("%d%d%d%d",&n,&a,&b,&c);
	a=a*a%mod; _b[0]=_c[0]=1;
	for(int i=1; i<=n; i++) _b[i]=_b[i-1]*b%mod,_c[i]=_c[i-1]*c%mod;
	for(int i=1; i<=n; i++) scanf("%lld%lld",&p[i].x,&p[i].y);
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=n; j++) if(i!=j) A[j-(i<j)]=p[j]-p[i];
		sort(A+1,A+n);
		int yjy=2,s1,aii=2,s2;
		for(int j=1; j<n; j++)
		{
			if(j==yjy) yjy=add(yjy); if(j==aii) aii=add(aii);
			while(fabs(A[j].t-A[yjy].t)<e&&abs(A[j].x)+abs(A[j].y)>abs(A[yjy].x)+abs(A[yjy].y))
			{
				if(yjy==aii) aii=add(aii);
				yjy=add(yjy);
			}
			while(A[j]*A[aii]>0) aii=add(aii);
			s1=(yjy-j+n-2)%(n-1);
			s2=(aii-yjy+n-1)%(n-1);
			ans=(ans+a*_b[s1]%mod*(_b[s2]-_c[s2]+mod)%mod*_c[n-s1-s2-2])%mod;
		}
	}
	printf("%lld",ans);
}

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