点阵中多边形(顶点在格点)面积S=a+b/2-1,其中a是严格在图形内部格点数,b是图形边界上格点数,证明:证矩形以及直角三角形满足,再证图形相加也满足,然后任何一个三角形都可以分解为一个矩形减去三个直角三角形,任何一个多边形都可以分解为三角形相加 ,得证。
应用,对面积和内部格点的要求可以转化为对边界格点要求,然后运用同余知识。
可以发现每个点坐标都是偶数的话,面积一定是偶数(正常格点图中任意一个三角形可以分为矩形减去至多3个直角三角形,故一定是1/2的倍数,坐标全部倍增后就一定是2的倍数了)。那么要求a是奇数就是要求b/2是偶数,即b模4余0,可以发现
同时又有任意两项相减要么模4余0,要么余2, 因此根据读入坐标x,y模4的情况分为4类,不难发现合法的情况就是至少两点同类。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define sc second
#define pb push_back
#define ll long long
#define trav(v, x) for(auto v:x)
#define VI vector<int>
#define all(x) (x).begin(),(x).end()
using namespace std;
const double eps = 1e-10;
const int N = 2e5 + 100;
const ll mod = 998244353;
/*
S = a + b/2 -1
S is even
a is odd
<=> b / 2 is even
<=> b % 4 == 0
(x1, y1)
(x2, y2)
(x3, y3)
x%4 y%4
e0 0 0
e1 0 2
e2 2 0
e3 2 2
1.all in one block is ok
2.two in one block and one in other block
*/
ll num[5];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
ll n;
cin >> n;
for(int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
x %= 4, y %= 4;
int bl = 0;
if(y == 2)++bl;
if(x == 2)bl += 2;
num[bl]++;
}
ll ans = 0;
for(int i = 0; i <= 3; i++)
{
ll nw = 0;
nw = num[i] * (num[i] - 1) * (num[i] - 2) / 6;
nw += num[i] * (num[i] - 1) / 2 * (n - num[i]);
ans += nw;
}
cout << ans << '\n';
}