题解:
给n个点
求能构成多少个三角形满足 公式
A=|x1y2 - y1x2 + x2y3 - y2x3 + x3y1 - y3x1|/2
的A为整数
其实也就是 绝对值号里面部分的结果为偶数。
对以x,y的值其实只有奇偶性有用,因此 全部值对2取模
poj1809,我们考虑反面情况
-----------------------
对x提取公因子
A=x1(y2-y3)
+x2(y3-y1)
+x3(y1-y2)
要不满足的话,显然至少一个为奇数
剩下的可以为 奇+奇(1)
或者偶数+偶数 (2)
考虑(1)
也就是有
y2-y3为奇数
y3-y1为奇数
y1-y2为奇数
而这显然不可能:
例如 y1 y2 y3 依次从小到大
y1与 y2间隔为奇数y,y2与y3间隔为奇数x
那么y1与y3的间隔显然是 奇数x+奇数y+1(y2这一个数)为偶数
所以只可能是情况1.:奇数+偶数+偶数
--------------------
y2-y3为奇数
y3-y1为 偶数
y1-y2为 奇数
因此
A=x1(y2-y3) 奇数 *奇数
+x2(y3-y1) 偶数 *奇数/偶数
+x3(y1-y2) 奇数 *偶数
具体点对为:
(1,1) (1,0) (0,1)
(1,1) (0,0) (0,1)
--------------------y的奇偶性反过来
(1,0) (0,1) (0,0)
(1,0) (1,1) (0,0)
因此 C(n,3)减去那部分即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod =1000007;
const int N=100000;
map<int ,int > mp[2];
int main()
{
int t,cnt=1;
cin>>t;
while(t--)
{
mp[0].clear();
mp[1].clear();
int n,a,b;
cin>>n;
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
a+=100000;
b+=100000;
a&=1;
b&=1;
mp[a][b]++;
}
ll ans=1LL*n*(n-1)*(n-2)/6;
ans-=1LL*mp[1][1]*mp[1][0]*mp[0][1];
ans-=1LL*mp[1][1]*mp[0][0]*mp[0][1];
ans-=1LL*mp[1][0]*mp[0][1]*mp[0][0];
ans-=1LL*mp[1][0]*mp[1][1]*mp[0][0];
printf("Scenario #%d:\n",cnt++);
printf("%lld\n\n",ans);
}
return 0;
}