AcWing - 5048. 无线网络 + 5049. 选人 -- 二分 + 组合数学

5048. 无线网络

这个题目使用二分找到最合适的r
然后寻找基站的位置

详细思路和细节见代码

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define ll long long
#define sf(x) scanf("%d", &x);
#define de(x) cout << x << " ";
#define Pu puts("");
const int N = 2e5 + 9;
int n, m, ans;
int a[N];
bool check(int x) {
    ll last = a[0] + x;
    int cnt = 1;  // 注意此时已经算安装了一个基站
    for (int i = 0; i < n; i++) {
        if (last + x >= a[i])
            continue;
        last = a[i] + x;
        cnt++;
    }
    // 如果三个基站已经满足,则说明此时的r大了,返回true
    if (cnt <= 3 && last + x >= a[n - 1])
        return true;
    return false;
}
int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] *= 2;  // 变为二倍很巧妙,因为在原来数据的情况下
        // 最多是会出现0.5
    }
    sort(a, a + n);  // 注意这里需要从小到大对坐标进行排序
    int l = 0, r = 1e9, mid;
    while (l < r) {  // 二分,找到第一个大于等于的
        mid = (l + r) / 2;
        if (check(mid))
            r = mid;
        else
            l = mid + 1;
    }
    printf("%.6lf\n", l / 2.0);

    queue<double> q;  // 接下来找放置基站的位置
    double last = a[0] + l;
    q.push(last / 2.0);  // 和二分里的check函数一样,依次向后找
    for (int i = 0; i < n; i++) {
        // de(last + l) de(a[i]) Pu;
        if (last + l >= a[i])
            continue;
        last = a[i] + l;
        // de(last) de(a[i]) Pu;
        // de(last) Pu;
        q.push(last / 2.0);
    }
    while (q.size() < 3) {
        q.push(0);
    }
    while (!q.empty()) {
        printf("%.6lf ", q.front());
        q.pop();
    }
    return 0;
}

5049. 选人

使用到了组合数学的知识,而且很巧妙的一点是,我们可以反过来求解不满足时的概率p,然后1-p即是我们要求解的值,最后记得保留6位小数输出
详细思路见代码

#include 
using namespace std;
#define ll long long
#define sf(x) scanf("%d", &x);
#define de(x) cout << x << " ";
#define Pu puts("");
const int N = 1e3 + 9, mod = 1e9 + 7;
int n, m, ans;
int a[N];
int main() {
    int h;
    cin >> n >> m >> h;
    h--;  // 注意我的数组下标是从0开始的
    int sz = 0;
    for (int i = 0; i < m; i++) {
        cin >> a[i];
        sz += a[i];
    }
    if (sz < n) {  // 全部选完也不够
        cout << "-1\n";
        return 0;
    }
    double res = 1;
    for (int i = 1; i < n; i++) {
        res *= 1.0 * (sz - a[h] - i + 1) / (sz - i);
    }
    printf("%.6lf\n", 1 - res);
    return 0;
}

你可能感兴趣的:(刷题+算法,AcWing,#,思维+模拟,算法)