解题思路
考虑当我们用叉积计算面积的时候,会以坐标轴上的一个点作为原点,在剩下的点中再枚举两个点,计算他们以原点的叉积。打过叉积的人会发现,这样算出来的一定是质数,但是是一个四边形的面积,则当他是偶数时,我们/2求出的三角形面积会是一个小数,与题意符合。
所以我们得出,叉积等于奇数时,面积是小数,回忆一下乘法奇偶性,我们需要一个横纵坐标奇偶性相反的(即一奇一偶),还需要一个横纵坐标都是奇数的。
我们把所有的点按照奇偶性归类,前奇后偶的个数为x,两个偶数个数为y,两个奇数个数为z,前偶后奇个数为k。我们枚举一个原点,考虑减去它,剩下的数奇偶性会发生什么变化。每次将
x
,
y
,
z
,
k
x,y,z,k
x,y,z,k更新。
a
n
s
+
=
z
∗
(
a
+
k
)
ans+=z*(a+k)
ans+=z∗(a+k)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define ll long long
#define db double
using namespace std;
ll n,x,y,z,k,ans;
struct c {
ll x,y;
int id,l,r;
} a[100010];
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%lld%lld",&a[i].x,&a[i].y);
if(abs(a[i].x)%2==a[i].y%2)
a[i].id=1;
if(abs(a[i].x)%2==0)a[i].l=1;
if(abs(a[i].y)%2==0)a[i].r=1;
if(a[i].l==1&&a[i].r==0)
x++;
if(a[i].l==1&&a[i].r==1)
y++;
if(a[i].l==0&&a[i].r==0)
z++;
if(a[i].l==0&&a[i].r==1)
k++;
}
for(int i=1; i<=n; i++) {
int a1,a2,a3,a4;
a1=x,a2=y,a3=z,a4=k;
if(a[i].l==1&&a[i].r==0) {
x--;
swap(x,y);
swap(z,k);
ans=ans+z*(x+k);
}
if(a[i].l==1&&a[i].r==1) {
y--;
ans=ans+z*(x+k);
}
if(a[i].l==0&&a[i].r==0) {
z--;
swap(x,k);
swap(y,z);
ans=ans+z*(x+k);
}
if(a[i].l==0&&a[i].r==1) {
k--;
swap(x,z);
swap(y,k);
ans=ans+z*(x+k);
}
x=a1,y=a2,z=a3,k=a4;
//cout<<ans;
}
printf("%lld",ans/2);
}