2010-1165

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

by vout
[[BR]]
给定x, y, a, b, k,随机输出范围在[0, a]和[0, b]的两个数p和q,求满足|x + y - (p + q)| <= k的概率。
[[BR]]
分三种情况考虑,以下不妨总设a > b:
[[BR]]
1. a = b = 0. 在这种情况下,必然有p = q = 0,因此只需要判断x + y <= k是否成立即可。这里有一个double的精度问题,要加eps判断:x + y <= k + eps。
[[BR]]
2. a > 0 而 b = 0. 必然有q = 0,只要判断p的取值范围,变为线段上的几何概型问题。
[[BR]]
3. a > 0 && b > 0. 此时p和q可取的区域为[0, a] * [0, b]的矩形,变为矩形上的几何概型问题。
[[BR]]
代码如下:[[BR]]

{{{
#!cpp
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cassert>
using namespace std;

const double eps = 1e-8;

int main() {
    double x, y, a, b, k;
    while (scanf("%lf%lf%lf%lf%lf", &x, &y, &a, &b, &k) != EOF) {
        if (a < b) {
            swap(a, b);
        }

        if (a == 0) {
            if (x + y <= k + eps) {
                printf("%.6f\n", 1.0);
            } else {
                printf("%.6f\n", 0.0);
            }
            continue;
        }

        double d = x + y;

        if (b == 0) {
            double l = min(max(0.0, d - k), a);
            double r = max(0.0, min(a, d + k));
            printf("%.6f\n", fabs(r - l) / a);
            continue;
        }

        double p1 = d + k;
        double p2 = d + k - b;
        double p3 = d + k;
        double p4 = d + k - a;

        double s1 = 0;

        if (p1 <= 0) {
            s1 = 0;
        } else if (p1 <= b) {
            s1 = 0.5 * p1 * p1;
        } else if (p1 <= a) {
            s1 = 0.5 * p1 * p1 - 0.5 * (p1 - b) * (p1 - b);
        } else if (p1 <= a + b) {
            s1 = a * b - 0.5 * (a + b - p1) * (a + b - p1);
        } else {
            s1 = a * b;
        }

        p1 = d - k;
        p2 = d - k - b;
        p3 = d - k;
        p4 = d - k - a;


        if (p1 <= 0) {
            s1 = s1;
        } else if (p1 <= b) {
            s1 -= 0.5 * p1 * p1;
        } else if (p1 <= a) {
            s1 -= 0.5 * p1 * p1 - 0.5 * (p1 - b) * (p1 - b);
        } else if (p1 <= a + b) {
            s1 -= a * b - 0.5 * (a + b - p1) * (a + b - p1);
        } else {
            s1 -= a * b;
        }

        printf("%.6f\n", fabs(s1) / a / b);
    }
    return 0;
}

}}}

by vout


给定x, y, a, b, k,随机输出范围在[0, a]和[0, b]的两个数p和q,求满足|x + y - (p + q)| <= k的概率。


分三种情况考虑,以下不妨总设a > b:


1. a = b = 0. 在这种情况下,必然有p = q = 0,因此只需要判断x + y <= k是否成立即可。这里有一个double的精度问题,要加eps判断:x + y <= k + eps。


2. a > 0 而 b = 0. 必然有q = 0,只要判断p的取值范围,变为线段上的几何概型问题。


3. a > 0 && b > 0. 此时p和q可取的区域为[0, a] * [0, b]的矩形,变为矩形上的几何概型问题。


代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cassert>
using namespace std;
const double eps = 1e-8;
int main() {
    double x, y, a, b, k;
    while (scanf("%lf%lf%lf%lf%lf", &x, &y, &a, &b, &k) != EOF) {
        if (a < b) {
            swap(a, b);
        }
        if (a == 0) {
            if (x + y <= k + eps) {
                printf("%.6f\n", 1.0);
            } else {
                printf("%.6f\n", 0.0);
            }
            continue;
        }
        double d = x + y;
        if (b == 0) {
            double l = min(max(0.0, d - k), a);
            double r = max(0.0, min(a, d + k));
            printf("%.6f\n", fabs(r - l) / a);
            continue;
        }
        double p1 = d + k;
        double p2 = d + k - b;
        double p3 = d + k;
        double p4 = d + k - a;
        double s1 = 0;
        if (p1 <= 0) {
            s1 = 0;
        } else if (p1 <= b) {
            s1 = 0.5 * p1 * p1;
        } else if (p1 <= a) {
            s1 = 0.5 * p1 * p1 - 0.5 * (p1 - b) * (p1 - b);
        } else if (p1 <= a + b) {
            s1 = a * b - 0.5 * (a + b - p1) * (a + b - p1);
        } else {
            s1 = a * b;
        }
        p1 = d - k;
        p2 = d - k - b;
        p3 = d - k;
        p4 = d - k - a;
        if (p1 <= 0) {
            s1 = s1;
        } else if (p1 <= b) {
            s1 -= 0.5 * p1 * p1;
        } else if (p1 <= a) {
            s1 -= 0.5 * p1 * p1 - 0.5 * (p1 - b) * (p1 - b);
        } else if (p1 <= a + b) {
            s1 -= a * b - 0.5 * (a + b - p1) * (a + b - p1);
        } else {
            s1 -= a * b;
        }
        printf("%.6f\n", fabs(s1) / a / b);
    }
    return 0;
}