[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;
    }
}
时间: 2024-10-22 01:34:45

[hdu5448 Marisa’s Cake]多边形面积,公式化简的相关文章

HDU 3982 半平面交+圆与多边形面积交

Harry Potter and J.K.Rowling Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 685    Accepted Submission(s): 210 Problem Description In July 31st, last month, the author of the famous novel seri

多边形面积公式

多边形面积公式 设点顺序 (x1 y1) (x2 y2)    ... (xn yn) 则面积等于 |x1   y1 |      |x2   y2|                  |xn   yn| 0.5 * abs( |            | +   |           | + ...... +   |           | ) |x2   y2 |      |x3   y3|                  |x1   y1| 其中        |x1   y1| |

三角剖分求多边形面积的交 HDU3060

1 //三角剖分求多边形面积的交 HDU3060 2 3 #include <iostream> 4 #include <cstdio> 5 #include <cstring> 6 #include <stack> 7 #include <queue> 8 #include <cmath> 9 #include <algorithm> 10 using namespace std; 11 12 const int max

poj 1654 Area(求多边形面积)

题意:从原点出发向八个方向走,所给数字串每个数字代表一个方向,终点与原点连线,求所得多边形面积: 思路:(性质)共起点的两向量叉积的一半为两向量围成三角形的面积.以此计算每条边首尾两个向量的叉积,求和,除二: #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const dou

poj1408——叉积求多边形面积

poj1408——叉积求多边形面积 Fishnet Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1853   Accepted: 1185 Description A fisherman named Etadokah awoke in a very small island. He could see calm, beautiful and blue sea around the island. The previou

地球椭球面上多边形面积量算(C++代码)

昨天突然测试的时候发现以前产品中写的地球椭球面上面积计算的代码有点问题,于是今天就彻底修正,从QGIS中抠出代码来用C++重写了一下,新代码可以比较准确计算椭球面上多边形的面积,这个基础函数对空间量算功能中的面积量测非常重要,在这里共享出来供大家参考甚至直接拿过去用. 头文件如下: /** * @file DistanceArea.h * @brief 椭球面上计算多边形面积的接口文件 * @details * @author zxg * @date 2015年5月15日 * @version

多边形面积模板

HDU 2036 改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 20033    Accepted Submission(s): 10256 Problem Description “ 改革春风吹满地, 不会AC没关系; 实在不行回老家, 还有一亩三分地. 谢谢!(乐队奏乐)”话说部分学生心态极好,每天就知道游戏,这次

HDU 3060 多边形面积并

Area2 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1197    Accepted Submission(s): 278 Problem Description 小白近期又被空军特招为飞行员,參与一项实战演习.演习的内容还是轰炸某个岛屿(这次的岛屿非常大,非常大非常大非常大,大到炸弹怎么扔都能全然在岛屿上引爆),看来小白确实是

Area - POJ 1654(求多边形面积)

题目大意:从原点开始,1-4分别代表,向右下走,向右走,向右上走,向下走,5代表回到原点,6-9代表,向上走,向左下走,向左走,向左上走.求出最后的多边形面积. 分析:这个多边形面积很明显是不规则的,可以使用向量积直接求出来面积即可. 代码如下: ------------------------------------------------------------------------------------------------------------------------------