题目连接:http://codeforces.com/gym/101873/problem/Gc++
题意:spa
在点阵上,给出 $N$ 个点的坐标(所有都是在格点上),将它们按顺序链接能够构成一个多边形,求该多边形内包含的格点的数目。code
题解:blog
首先,根据皮克定理 $S = a + \frac{b}{2} - 1$,其中 $S$ 是多边形面积,$a$ 是多边形内部格点数目,$b$ 是多边形边界上的格点数目。ci
那么,咱们只要求出 $S$ 和 $b$,就很好求得 $a$ 了:get
一、对于两端点 $(x_1,y_1),(x_2,y_2)$ 都再格点上的一条线段,该线段上的格点数目为 $\gcd(|x_1-x_2|,|y_1-y_2|)+1$。这很好理解,对于横坐标差值和纵坐标差值求得的最大公因数 $g$,至关于将横坐标差值分红 $g$ 份,因为是整除,所以显然每份的左右端点都是整数,对于纵坐标也是一样的道理,因为是最大公因数,因此不可能再分更多份,所以 $\gcd(|x_1-x_2|,|y_1-y_2|)$ 即求得两端点间最多能分红多少段由格点分割的线段,再加上 $1$ 即整条线段上的格点数目。it
二、对于格点按顺序给出的多边形,设 $P_0 = P_{n+1}$ 且 $O$ 为原点,则面积为 $\frac{1}{2} \sum_{i=0}^{n}{\left ( \overrightarrow{OP_i} \times \overrightarrow{OP_{i+1}} \right )}$。这个画个图模拟一下也很是容易理解。class
AC代码:gc
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int maxn=1e5+10; int n; pll p[maxn]; inline ll gcd(ll m,ll n){return n?gcd(n,m%n):m;} int main() { cin>>n; for(int i=0;i<n;i++) scanf("%lld%lld",&p[i].first,&p[i].second); ll S2=0, b=0; for(int i=0;i<n;i++) { S2+=p[i].first*p[(i+1)%n].second-p[i].second*p[(i+1)%n].first; b+=gcd(abs(p[i].first-p[(i+1)%n].first),abs(p[i].second-p[(i+1)%n].second)); } cout<<(abs(S2)-b+2)/2<<endl; }