• Gym 101873G


    题目链接:http://codeforces.com/gym/101873/problem/G

    题意:

    在点阵上,给出 $N$ 个点的坐标(全部都是在格点上),将它们按顺序连接可以构成一个多边形,求该多边形内包含的格点的数目。

    题解:

    首先,根据皮克定理 $S = a + frac{b}{2} - 1$,其中 $S$ 是多边形面积,$a$ 是多边形内部格点数目,$b$ 是多边形边界上的格点数目。

    那么,我们只要求出 $S$ 和 $b$,就很好求得 $a$ 了:

    1、对于两端点 $(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$ 即整条线段上的格点数目。

    2、对于格点按顺序给出的多边形,设 $P_0 = P_{n+1}$ 且 $O$ 为原点,则面积为 $frac{1}{2} sum_{i=0}^{n}{left ( overrightarrow{OP_i} imes overrightarrow{OP_{i+1}} ight )}$。这个画个图模拟一下也非常容易理解。

    AC代码:

    #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;
    }
  • 相关阅读:
    如何提高沟通能力?
    如何做到科学决策?推荐你看这本《决策必读12篇》
    领导者如何让员工真心服从自己?
    MBA看什么书,MBA教材书目推荐
    有关战略管理的书,哪本最值得推荐?
    市场营销必看书籍推荐
    P1208 混合牛奶题解
    P5019 铺设道路题解
    P1728 陶陶摘苹果题解
    P1106 删数问题题解
  • 原文地址:https://www.cnblogs.com/dilthey/p/9873966.html
Copyright © 2020-2023  润新知