题目大意:
给你一个由3个整点构成的三角形,要你求出该三角形内部的整点个数.
解题思路:
用了一个非常神奇的小定理:Pick定理。
由Pick定理,一个多边形如果每个顶点都由整点构成,该多边形的面积为S,该多边形边上的整点为L,内部的整点为N,则有:2S=2N+L-2。
那么我们要求的N即为(2S+2-L)/2。
S可由向量叉积得到,关键是求三角形各边上有多少个整点。
假设有一条由两个整点构成的线段,该线段该线段X方向的增量绝对值为DX, Y方向的增量绝对值为DY. 设线段内部(不含端点)整点个数为ans:
DX=DY=0时, ans=0
DX=0时, ans=DY-1(等价于gcd(DX,DY)-1 )
DY=0时, ans=DX-1 (等价于gcd(DX,DY)-1 )
DX!=0且DY!=0时, ans=gcd(DX,DY)-1
PS:poj编译器太老了,bits不能用,读入优化也会出问题。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#define ll long long
using namespace std;
const int N=100005;
struct point
{
int x,y;
point(){}
point(int _x,int _y):x(_x),y(_y){}
inline friend point operator - (const point &a,const point &b)
{return point(a.x-b.x,a.y-b.y);}
inline friend int operator * (const point &a,const point &b)
{return a.x*b.y-a.y*b.x;}
};
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int calc(point a)
{
if(!a.x&&!a.y)return 0;
return gcd(abs(a.x),abs(a.y))-1;
}
int main()
{
//freopen("lx.in","r",stdin);
point a,b,c;
while(scanf("%d%d%d%d%d%d",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y))
{
if(!a.x&&!a.y&&!b.x&&!b.y&&!c.x&&!c.y)break;
int S=abs((c-a)*(b-a));
int num=calc(a-b)+calc(a-c)+calc(b-c)+3;
cout<<(S+2-num)/2<<'\n';
}
return 0;
}