zoukankan      html  css  js  c++  java
  • [hdu5448 Marisa’s Cake]多边形面积,公式化简

    题意:给一个凸多边形,求任选若干点形成的多边形的面积和。

    思路:

    • 按一定方向(顺时针或逆时针)对多边形的顶点进行编号,则多边形的面积计算公式为:f1 x f2 + fx f3 + ... fn-1 x f+ fn x f1,f表示从参考点到i的向量。
    • 考虑fx fj 在答案中出现的次数,则答案可以写成:fi x fj * 2n-(j-i+1) (i<j) 或 fx f* 2i-j-1(i>j),直接枚举i和j是O(n2)的,显然不行。
    • 由叉积的性质:∑(fi x P) = (∑fi) x P,可以预处理出fi*2i-1的前缀和以及fi/2i+1的前缀和,复杂度O(n),从而只需枚举一维,另一维的和O(1)得到,总复杂度O(n)。
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    #pragma comment(linker, "/STACK:10240000")
    #include <bits/stdc++.h>
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    
    namespace Debug {
    void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<" ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    }
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    /* -------------------------------------------------------------------------------- */
    
    const int maxn = 1e5 + 7;
    const int mod = 1e9 + 7;
    
    struct Point {
        ll x, y;
        void read() {
            int x, y;
            scanf("%d%d", &x, &y);
            this->x = x;
            this->y = y;
        }
        Point(int x, int y) {
            this->x = x;
            this->y = y;
        }
        Point() {}
        Point operator + (const Point &that) const {
            return Point((x + that.x) % mod, (y + that.y) % mod);
        }
        Point operator * (const int &m) const {
            return Point(x * m % mod, y * m % mod);
        }
    };
    Point p[maxn], g[maxn], h[maxn];
    int two[maxn], twoinv[maxn];
    
    int cross(Point &a, Point &b) {
        return (a.x * b.y % mod - a.y * b.x % mod + mod) % mod;
    }
    
    int powermod(int a, int n, int mod) {
        ll ans = 1, buf = a;
        while (n) {
            if (n & 1) ans = (ans * buf) % mod;
            buf = buf * buf % mod;
            n >>= 1;
        }
        return ans;
    }
    
    void init() {
        ll inv = powermod(2, mod - 2, mod);
        two[0] = twoinv[0] = 1;
        for (int i = 1; i < maxn; i ++) {
            two[i] = (two[i - 1] + two[i - 1]) % mod;
            twoinv[i] = twoinv[i - 1] * inv % mod;
        }
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int T, n;
        cin >> T;
        init();
        while (T --) {
            cin >> n;
            for (int i = 1; i <= n; i ++) {
                p[i].read();
                g[i] = g[i - 1] + p[i] * two[i - 1];
                h[i] = h[i - 1] + p[i] * twoinv[i + 1];
            }
            int ans = 0;
            for (int i = 2; i <= n; i ++) {
                Point buf = p[i] * two[n - i];
                ans = (ans + cross(g[i - 1], buf)) % mod;
            }
            for (int i = 2; i <= n; i ++) {
                Point buf = p[i] * two[i];
                ans = (ans + cross(buf, h[i - 1])) % mod;
            }
            cout << ans << endl;
        }
    }
    
  • 相关阅读:
    使用 RemObjects SDK 建立 WebService 应用
    Excel文件读写的.NET开源组件 Koogra Excel BIFF/XLSX Reader Library
    DataSnap 2009 系列之三 (生命周期篇)
    更改SQL Server表所有者的操作方法
    delphi调用cmd的两种方法
    用AndroidX86和VirtualBox打造高性能Android开发环境
    DevExpress 换肤
    Remobjects关于Channel is Busy 错误的解决方法
    关于D7“System.pas not found”错误的解决方法
    40 套漂亮的图标
  • 原文地址:https://www.cnblogs.com/jklongint/p/4809042.html
Copyright © 2011-2022 走看看