IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Codeforces 559D Pick 定理 + 数学期望 -> 正文阅读

[数据结构与算法]Codeforces 559D Pick 定理 + 数学期望

题解

传送门 Codeforces 559D Randomizer

题解

已知 n n n 个点构成的严格凸多边形,求其中可构成非退化的凸多边形的点集,所构成的多边形内部格点(整数坐标点)数量的数学期望。

满足条件的点集规模至少为 3 3 3。这样的点集构成的凸多边形可以看作是原始凸多边形切割数个凸多边形后得到。那么可以枚举 O ( n 2 ) O(n^2) O(n2) 的被切割的凸多边形,计算不被包含在多边形内部格点数量的数学期望。假设所有原始凸多边形内部的格点都被点的子集构成的凸多边形包含,最后减去上述数学期望,即为所求。

被切割的凸多边形除了一条边以外,其余的边都是原始凸多边形上的位置连续边。那么可以固定端点 i i i,根据 Pick 定理,不断计算 i , i + 1 , ? ? , i + k i,i+1,\cdots,i+k i,i+1,?,i+k 所构成的凸多边形上,属于原始凸多边形内部的格点。被切割的凸多边形的点集为 i , i + 1 , ? ? , i + k i,i+1,\cdots,i+k i,i+1,?,i+k 时,满足条件的凸多边形数量,占总的子集构成的凸多边形数量为
2 n ? k ? 1 ? ( n 0 ) 2 n ? ( n 0 ) ? ( n 1 ) ? ( n 2 ) \frac{2^{n-k-1}-\binom{n}{0}}{2^n-\binom{n}{0}-\binom{n}{1}-\binom{n}{2}} 2n?(0n?)?(1n?)?(2n?)2n?k?1?(0n?)? 实际上, 2 1 0 5 2^{10^5} 2105 超出了 long double 型的表示范围,而且 O ( n 2 ) O(n^2) O(n2) 时间复杂度过大。考虑误差,取 k k k 至多为 64 64 64 即可;当 n n n 过大时, 2 n 2^n 2n 远大于 ( n k ) , 0 ≤ k ≤ 2 \binom{n}{k},0\leq k\leq 2 (kn?),0k2,那么将上述数量的比值取 1 2 k + 1 \frac{1}{2^{k+1}} 2k+11? 即可。

#include <bits/stdc++.h>
using namespace std;
typedef long double db;
typedef long long ll;
const int MAXN = 1E5 + 5;
struct P
{
    ll x, y;
    ll det(P p) { return x * p.y - p.x * y; }
    P operator-(P p) { return {x - p.x, y - p.y}; }
} ps[MAXN];
int N;
db pw[105], f[105];

ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

int add(int x, int d)
{
    x += d;
    return x >= N ? x - N : x;
}

db get(int k) { return N >= 100 ? pw[k + 1] : f[k]; }

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> N;
    for (int i = 0; i < N; ++i)
        cin >> ps[i].x >> ps[i].y;
    db sum = 2;
    for (int i = 0; i < N; ++i)
    {
        int j = add(i, 1);
        ll x = ps[i].x - ps[j].x, y = ps[i].y - ps[j].y;
        sum += abs(ps[i].det(ps[j])) - gcd(abs(x), abs(y));
    }
    pw[0] = 1;
    for (int i = 0; i < 100; ++i)
        pw[i + 1] = pw[i] / 2;
    if (N < 100)
    {
        db down = pow((db)2, N) - 1 - N - (db)N * (N - 1) / 2;
        for (int i = 1; i < min(N, 64); ++i)
            f[i] = (pow((db)2, N - i - 1) - 1) / down;
    }
    db del = 0;
    for (int i = 0; i < N; ++i)
    {
        db t = 0;
        for (int k = 1; k < min(N, 64); ++k)
        {
            int u = add(i, k), v = add(i, k - 1);
            ll x = ps[u].x - ps[v].x, y = ps[u].y - ps[v].y;
            t += abs((ps[u] - ps[i]).det(ps[v] - ps[i])) - gcd(abs(x), abs(y));
            if (k > 1)
            {
                ll x2 = ps[u].x - ps[i].x, y2 = ps[u].y - ps[i].y;
                del += get(k) * (t + gcd(abs(x2), abs(y2)));
            }
        }
    }
    cout << fixed << setprecision(9) << (sum - del) / 2 << '\n';
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:50:37  更:2022-02-28 15:54:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:37:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码