E - ConvexScore
Time limit : 2sec / Memory limit : 256MB
Score : 700 points
Problem Statement
You are given N points (xi,yi) located on a two-dimensional plane. Consider a subset S of the N points that forms a convex polygon. Here, we say a set of points S forms a convex polygon when there exists a convex polygon with a positive area that has the same set of vertices as S. All the interior angles of the polygon must be strictly less than 180°.
cddb0c267926c2add885ca153c47ad8a.png
For example, in the figure above, {A,C,E} and {B,D,E} form convex polygons; {A,C,D,E}, {A,B,C,E}, {A,B,C}, {D,E} and {} do not.
For a given set S, let n be the number of the points among the N points that are inside the convex hull of S (including the boundary and vertices). Then, we will define the score of S as 2n−|S|.
Compute the scores of all possible sets S that form convex polygons, and find the sum of all those scores.
However, since the sum can be extremely large, print the sum modulo 998244353.
Constraints
1≤N≤200
0≤xi,yi<104(1≤i≤N)
If i≠j, xi≠xj or yi≠yj.
xi and yi are integers.
Input
The input is given from Standard Input in the following format:
N
x1 y1
x2 y2
:
xN yN
Output
Print the sum of all the scores modulo 998244353.
Sample Input 1
4
0 0
0 1
1 0
1 1
Sample Output 1
5
We have five possible sets as S, four sets that form triangles and one set that forms a square. Each of them has a score of 20=1, so the answer is 5.
Sample Input 2
5
0 0
0 1
0 2
0 3
1 1
Sample Output 2
11
We have three “triangles” with a score of 1 each, two “triangles” with a score of 2 each, and one “triangle” with a score of 4. Thus, the answer is 11.
Sample Input 3
1
3141 2718
Sample Output 3
0
There are no possible set as S, so the answer is 0.
题目大意:给出一些点,每个凸多边形的贡献为
2n−|S|
,求贡献和。
解题思路:将贡献与凸多边形内的点的子集形成双射,然后暴力枚举判断即可。
解法一:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN=205;
const int MOD=998244353;
int x[MAXN],y[MAXN];
LL Q_pow(LL x,LL n)
{
LL res=1;
while(n>0)
{
if(n&1) res=res*x%MOD;
x=x*x%MOD;
n>>=1;
}
return res;
}
int main()
{
int n;
while(scanf("%lld",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d%d",&x[i],&y[i]);
LL ans=Q_pow(2,n);
ans=(ans-1+MOD)%MOD;//空集
ans=(ans-n+MOD)%MOD;//单元素
ans=(ans-n*(n-1)/2+MOD)%MOD;//双元素
int A,B,C;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
A=y[j]-y[i];
B=x[i]-x[j];
C=-A*x[i]-B*y[i];
LL cnt=2;//i j
for(int k=1;k<=n;k++)
{
if(k==i||k==j) continue;
if(A*x[k]+B*y[k]+C!=0) continue;
if(k<j) break;
cnt++;
}
ans=(ans-Q_pow(2,cnt)+MOD)%MOD;
ans=(ans+1)%MOD;
ans=(ans+cnt)%MOD;
ans=(ans+cnt*(cnt-1)/2)%MOD;
}
}
printf("%lld\n",ans);
}
return 0;
}
解法二:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN=205;
const int MOD=998244353;
struct point
{
int x,y;
point(int _x=0,int _y=0):x(_x),y(_y){}
}p[MAXN];
point operator - (const point& a,const point& b)
{
return point(a.x-b.x,a.y-b.y);
}
int cross(const point& a,const point& b)
{
return a.x*b.y-a.y*b.x;
}
int dot(const point& a,const point& b)
{
return a.x*b.x+a.y*b.y;
}
LL Q_pow(LL x,LL n)
{
LL res=1;
while(n>0)
{
if(n&1) res=res*x%MOD;
x=x*x%MOD;
n>>=1;
}
return res;
}
int main()
{
int n;
while(scanf("%lld",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
LL ans=Q_pow(2,n);
ans=(ans-1+MOD)%MOD;
ans=(ans-n+MOD)%MOD;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
LL cnt=0;
for(int k=1;k<=n;k++)
{
if(cross(p[k]-p[i],p[k]-p[j])==0&&dot(p[k]-p[i],p[k]-p[j])<0)
++cnt;
}
ans=(ans-Q_pow(2,cnt)+MOD)%MOD;
}
}
printf("%lld\n",ans);
}
return 0;
}