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;
        }
    }
    
  • 相关阅读:
    Path,Files巩固,题目:从键盘接收两个文件夹路径,把其中一个文件夹中(包含内容)拷贝到另一个文件夹中
    JavaSE复习_11 IO流复习
    JavaSE复习_10 多线程复习
    采用多线程和生产者消费者模式来实现对于一个目录以及所有子目录下的文件内容的搜索,打印出包含指定关键字的行.
    多线程_多生产者多消费者的实现问题
    算法_栈与队列的Java链表实现
    算法_队列的Java通用数组实现
    vuex之单向数据流
    原生JS实现瀑布流布局
    addEventListener调用带参数函数
  • 原文地址:https://www.cnblogs.com/jklongint/p/4809042.html
Copyright © 2011-2022 走看看