AcWing 5566. 盖楼 -- 二分 + 容斥原理

约翰计划在农田附近盖一栋 \(H\) 层的高楼。

楼层自下而上依次编号为 \(1 \sim H\)

为了防止奶牛们集体反对,约翰需要贿赂两头奶牛头目----贝茜和贝蒂。

约翰和两头奶牛约定,在高楼建成后,约翰需要挑选其中的 \(N\) 个楼层送给贝茜,\(M\) 个楼层送给贝蒂。

显然,一个楼层最多只能送给一头奶牛。

贝茜不喜欢能被质数 \(x\) 整除的数字,因此它不接受编号能被 \(x\) 整除的楼层。

贝蒂不喜欢能被质数 \(y\) 整除的数字,因此它不接受编号能被 \(y\) 整除的楼层。

请你计算,为了让两头奶牛都能满意从而使得高楼可以顺利搭建,这栋高楼至少需要盖多少层,即请你计算满足条件的 \(H\) 的最小可能值。

输入格式

共一行,包含四个整数 \(N,M,x,y\)

输出格式

一个整数,表示 \(H\) 的最小可能值。

数据范围

\(3\) 个测试点满足 \(1 \le N,M \le 10\)
所有测试点满足 \(1 \le N,M < 10^9\)\(N+M \le 10^9\)\(2 \le x < y \le 30000\),保证 \(x,y\) 均是质数。

输入样例1:

3 1 2 3

输出样例1:

5

输入样例2:

1 3 2 3

输出样例2:

4

题解

倒是很容易想到用二分来做 因为最小楼层数可以二分 当小于最小楼层数就不符合答案 楼层数大于最小楼层数 贝希和贝蒂就都能选完他们的楼层
但是check()函数该怎么写确实是难题
由题 贝西需要不被x整除的整数 贝蒂需要不被y整除的整数
233f370d490e0edcdf562ff6df332ae.jpg
注释① 由于送给贝西的数能被y整除(这样才能不被包含进集合B) 所以送给贝西的数需要在能被y整除的数中选,能被y整除的数\(\lfloor\frac{H}{y}\rfloor\) 在这些数里面我们还需要剔除能被x整除的数\(\lfloor\frac{H}{xy}\rfloor\)
所以最终是\(\lfloor\frac{H}{y}\rfloor - \lfloor\frac{H}{xy}\rfloor\)
注释②\(①\)同理
注释③ 那么既不能被x整除也不能被y整除的数就需要在全部数种减去能被x和y整除的数 再加上减了两次的能被x和y都整除的数的个数 \(H- (\lfloor\frac{H}{y}\rfloor + \lfloor\frac{H}{x}\rfloor) + \lfloor\frac{H}{xy}\rfloor\)
当贝西选了A个楼层贝蒂选了B个楼层 他们还缺的楼层要用C来补 如果C能补完 那就是合法的楼层高度
很绕 本题还要注意爆int的问题 开成longlong

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

int n, m, x, y;

bool check(LL mid)
{
    LL a = mid / y - mid / (x * y); //只能送给贝西的楼层
    LL b = mid / x - mid / (x * y); //只能送给贝蒂的楼层
    LL c = mid - (mid / x + mid / y) + mid / (x * y); //都能送的楼层
    LL s1 = max(0ll, n - a); //贝西还缺的楼层 这里取max的原因是 如果a已经够了贝西需要的楼层数 那n-a就会是负数 此时不缺楼层了 与0取max
    LL s2 = max(0ll, m - b); //贝蒂还缺的楼层
    if (c >= s1 + s2) return true; //都能送的楼层够用就返回true
    else return false;
}

void solve()
{
    scanf("%d%d%d%d", &n, &m, &x, &y);
    LL l = 1, r = 1e18; //直接开到long long上限 因为你不知道需要有多少楼层 当x和y是2 3时那就有非常多的楼层不满足要求 那最大楼层数就会非常大 所以我们直接开到上限
    while (l < r)
    {
        //在数轴上答案最小楼层数的右边是满足要求的 那我们就是求左边界
        LL mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    printf("%lld", r);
    return;
}

int main()
{
    solve();

    return 0;
}

AcWing-5566-盖楼-AcWing.png
好图 来自@美琴

posted @ 2024-04-16 16:02  MsEEi  阅读(14)  评论(0)    收藏  举报