本文主要是介绍hdu 5448 Marisa’s Cake(几何+凸包),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目链接:hdu 5448 Marisa’s Cake
解题思路
这题和zoj 3871 Convex Hull有点像,不过点数比较大,不能接受 o(n2) 的算法。但是题目给定的是一个凸包,所以可以通过化简,在 o(n) 的复杂度内计算出答案。
首先,对于一个三角形ABC
SABC=fA×fB+fB×fC+fC×fA(fi表示点i和原点组成的向量)
那么对于i和j两点,只需要计算 fi×fj 和 fj×fi 对ans的贡献值是多少即可。
ans=∑i=1n∑j=1i−1((2i−j−1−1)×fi×fj+(2n−i+j−1−1)×fj×fi)
ans=∑i=1n∑j=1i−1(2i−j−1×fi×fj−fi×fj+2n−i+j−1×fj×fi−fj×fi)
ans=∑i=1n∑j=1i−1(2i−j−1×fi×fj+2n−i+j−1×fj×fi)
ans=∑i=1n(2i−1fi×∑j=1i−1(2−jfj)+∑j=1i−1(2jfj)×2n−i−1fi)
在过程中维护 ∑i−1j=1(2−jfj) 和 ∑i−1j=1(2jfj)
代码
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;
typedef long long ll;
const int maxn = 100005;
const int mod = 1e9 + 7;struct Point {int x, y;Point(int x = 0, int y = 0): x(x), y(y) {}void read () { scanf("%d%d", &x, &y); }int operator * (const Point& u) { return (1LL * x * u.y % mod - 1LL * y * u.x % mod + mod) % mod; }Point operator * (const int u) { return Point(1LL * u * x % mod, 1LL * u * y % mod); }Point operator + (const Point& u) { return Point((x+u.x)%mod, (y+u.y)%mod); }
};int N, mul[maxn], inv[maxn];int mul_mod(ll x, int n, int mod) {int ret = 1;while (n) {if (n&1) ret = x * ret % mod;x = x * x % mod;n >>= 1;}return ret;
}int main () {mul[0] = inv[0] = 1;for (int i = 1; i < maxn; i++) mul[i] = 2 * mul[i-1] % mod;ll inv2 = mul_mod(2, mod-2, mod);for (int i = 1; i < maxn; i++) inv[i] = inv2 * inv[i-1] % mod;int cas;scanf("%d", &cas);while (cas--) {int ans = 0;scanf("%d", &N);Point fi, fg, fh;for (int i = 1; i <= N; i++) {fi.read();ans = (ans + 1LL * mul[i-1] * (fi * fh) % mod) % mod;ans = (ans + 1LL * (i==N?inv2:mul[N-i-1]) * (fg * fi) % mod) % mod;fg = fg + fi * mul[i];fh = fh + fi * inv[i];}printf("%d\n", ans);}return 0;
}
这篇关于hdu 5448 Marisa’s Cake(几何+凸包)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!