題目
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);
}