皮克定理,多边形面积以及线段上整点个数

皮克定理,多边形面积以及拓展欧几里得算法的奇特应用

皮克定理

皮克定理给出了顶点在格点上的多边形的面积公式:

引自百度百科的图1:

2 S = 2 a + b − 2 \begin{aligned} 2S=2a+b-2 \end{aligned} 2S=2a+b2
其中 a a a表示多边形内部的点数, b b b表示多边形边界上的整数点个数, S S S表示多边形的面积。

多边形面积

多边形可以划分成多个三角形,其面积就等于三角形面积之和。而三角形面积可以通过叉乘来求。

非常自然的,我们可以从多边形任意一个顶点 p 0 p_0 p0出发,连一条到其他每一个点的连线。

引自大佬博客的图2
通过对每一个三角形叉乘求面积,就可以求出多边形面积

简化:
事实上, p 0 p_0 p0点大可不必选择多边形顶点。对于平面上任意一点,与 p 1 , p 2 , . . . , p n p_1,p_2,...,p_n p1p2...pn所得三角形的面积就等于多边形面积(证明略,一种可行的证明方法是设出 p 0 p_0 p0点,列出叉乘的表达式,最后发现展开之后与 p 0 p_0 p0无关)。因此,方便起见,我们可以选择原点作为 p 0 p_0 p0

代码:

scanf("%d", &n); // n表示点的个数
for (int i = 0; i < n; i++)
{
	scanf("%d%d", &x[i], &y[i]);
}
long long s = 0;
for (int i = 1; i <= n; i++) { 
	// 向量p0->px就是点px的坐标
	// 通过取模最后算p0和p(n-1)的叉乘
	s += x[i % n] * y[i - 1] - x[i - 1] * y[i % n];
}
printf("%lld", s);

线段上整数点个数

对于一条两顶点在整数点上的线段,顶点为 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1, y_1),(x_2, y_2) (x1,y1)(x2,y2)。想要求在这条线段上的整数点的个数。

结论是:整数点的个数 s = g c d ( ∣ x 1 − x 2 ∣ , ∣ y 1 − y 2 ∣ ) + 1 s=gcd(|x_1-x_2|,|y_1-y_2|)+1 s=gcd(x1x2,y1y2)+1
x 2 = Δ x = p d , y 2 = Δ y = q d x_2=\Delta x=pd,y_2 = \Delta y=qd x2=Δx=pdy2=Δy=qd

直观理解:
观察方程 g = g c d ( ∣ x 1 − x 2 ∣ , ∣ y 1 − y 2 ∣ ) , g g=gcd(|x_1-x_2|,|y_1-y_2|),g g=gcd(x1x2,y1y2)g ∣ x 1 − x 2 ∣ , ∣ y 1 − y 2 ∣ |x_1-x_2|,|y_1-y_2| x1x2,y1y2的公因子,所以
{ g = p ∣ x 1 − x 2 ∣ g = q ∣ y 1 − y 2 ∣ \begin{cases} \text{$g=p|x_1-x_2|$}\\ \text{$g=q|y_1-y_2|$} \end{cases} {g=px1x2g=qy1y2
因此, ∣ x 1 − x 2 ∣ , ∣ y 1 − y 2 ∣ |x_1-x_2|,|y_1-y_2| x1x2,y1y2可分为 g g g个长为 p p p的份, g g g的长度为 q q q的份 ( g ∈ Z ) (g\in Z) (gZ),也即整个线段被分成 g g g份,所以整数点有 g + 1 g+1 g+1

证明:
为简化过程,不妨以线段的一个顶点重新建立坐标系
则可以设 Δ x = x 2 , Δ y = y 2 , d = g c d ( Δ x , Δ y ) \Delta x=x_2,\Delta y = y_2,d = gcd(\Delta x, \Delta y) Δx=x2,Δy=y2,d=gcd(Δx,Δy),再设 p , q p,q p,q,与 x , y , d x,y,d x,y,d之间有如下关系:
{ x 2 = Δ x = p d y 2 = Δ y = q d \begin{cases} x_2=\Delta x=pd\\ y_2 = \Delta y=qd\\ \end{cases} {x2=Δx=pdy2=Δy=qd

设点 ( x 1 + a , y 1 + h ) (x_1+a,y_1+h) (x1+a,y1+h)是线段上一点,由三角形相似得:
a Δ x = h Δ y = > a = h Δ x Δ y = h p d q d = h p q \frac{a}{\Delta x} = \frac{h}{\Delta y}\quad=>\quad a=h\frac{\Delta x}{\Delta y}=h\frac{pd}{qd}=h\frac{p}{q} Δxa=Δyh=>a=hΔyΔx=hqdpd=hqp

点在线段上,所以h的取值范围为 [ 0 , y 2 ] [0,y_2] [0,y2](别忘了我们已经重新建立了坐标系)。我们可以枚举 h h h [ 0 , y 2 ] [0,y_2] [0,y2]中每一个整数,如果此时 a a a也是整数,说明该点是一个整数点

a a a是整数时, p p p q q q的因子。因此,整数点的个数 s u m sum sum可以表示成(记号 [ 命 题 ] [命题] []表示命题为真时该表达式值为1,否则值为0。 [ q ∣ i p ] [q|ip] [qip]即表示 q ∣ i p q|ip qip为真时值为1,否则值为0,下式即是对 i i i 0 0 0 y 2 y_2 y2的情况求和):

s u m = ∑ i = 0 y 2 [ q ∣ i p ] \begin{aligned} sum = \sum_{i=0}^{y_2}{[q|ip]} \end{aligned} sum=i=0y2[qip]

g c d ( p , q ) = 1 , p q gcd(p,q)=1,pq gcd(p,q)=1,pq互质,所以 q ∣ i p    ⟺    q ∣ i q|ip\iff q|i qipqi,又因为 y 2 = q d y_2=qd y2=qd,上式可化简为:

s u m = ∑ i = 0 y 2 [ q ∣ i ] = ∑ i = 0 q d [ q ∣ i ] \begin{aligned} sum &= \sum_{i=0}^{y_2}{[q|i]}\\ &= \sum_{i=0}^{qd}{[q|i]}\\ \end{aligned} sum=i=0y2[qi]=i=0qd[qi]

继续化简(当 i i i可以为 q , 2 q , . . . , d q q,2q,...,dq q,2q,...,dq [ q ∣ i ] [q|i] [qi]为真,共d个),
s u m = ∑ i = 0 d = d + 1 \begin{aligned} sum&=\sum_{i=0}^{d}\\ &=d+1 \end{aligned} sum=i=0d=d+1

例题 GCPC2017G Water Testing

最后给一道例题

You just bought a large piece of agricultural land, but you noticed that – according to regulations you have to test the ground water at specific points on your property once a year. Luckily the description of these points is rather simple. The whole country has been mapped using a Cartesian Coordinate System (where (0; 0) is the location of the Greenwich Observatory). The corners of all land properties are located at integer coordinates according to this coordinate system. Test points for ground water have to be erected on every point inside a property whose coordinates are integers.

Input The input consists of:
one line with a single integer n ( 3 ≤ n ≤ 100000 ) n (3 \leq n \leq100 000) n(3n100000), the number of corner points of your property;
n lines each containing two integers x and y ( − 1 0 6 ≤ x , y ≤ 1 0 6 ) (-10^6\leq x,y \leq 10^6) (106x,y106), thecoordinates of each corner.
The corners are ordered as they appear on the border of your property and the polygon described by the points does not intersect itself.

Output The number of points with integer coordinates that are strictly inside your property. Sample Input 1 Sample Output
4
0 0
0 10
10 10
10 0

AC代码:

#include <bits/stdc++.h>
using namespace std;

long long x[1000000], y[1000000];

int main () {
	int n; cin >> n;
	for (int i = 0; i < n; i++) cin >> x[i] >> y[i];

	long long a = 0, b = 0;
	for (int i = 1; i <= n; i++) {
		a += x[i%n]*y[i-1] - x[i-1]*y[i%n];
		b += __gcd(abs(x[i%n]-x[i-1]),abs(y[i%n]-y[i-1]));
	}
	
	cout << (abs(a)-b+2)/2 << endl;	
}

  1. https://baike.baidu.com/item/%E7%9A%AE%E5%85%8B%E5%AE%9A%E7%90%86/7554085?fr=aladdin ↩︎

  2. https://www.cnblogs.com/xiexinxinlove/p/3708147.html ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值