[Codeforces #275 (Div. 2)B. Friends and Presents] 二分

本文介绍了一道 Codeforces 编程竞赛题目的解法,利用二分查找来确定满足条件的最小数值 v。题目要求将一定范围内的整数分为两组,每组数量固定且不包含特定倍数的数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[Codeforces #275 (Div. 2)B. Friends and Presents] 二分

题目链接[Codeforces #275 (Div. 2)B. Friends and Presents]
题意描述:从 1,2,,v 中选择若干个数组成两个集合 A B。满足 |A|=cnt1 , |B|=cnt2 ,并且集合 A 中不含x的倍数,集合 B 中不含y的倍数。求最小的 v
解题思路:很明显的单调性,直接对v进行二分就好了。

#include <bits/stdc++.h>
using namespace std;

typedef __int64 LL;

const LL INF = (1LL << 60);

LL N, M, X, Y;
LL v;
LL gcd(LL a, LL b) {
    while(b ^= a ^= b ^= a %= b);
    return a;
}
LL lcm(LL a, LL b) {
    return a / gcd(a, b) * b;
}
bool check(LL k) {
    LL a, b, c, temp;
    LL A = N, B = M;
    temp = k / lcm(X, Y);
    a = k / X - temp;
    b = k / Y - temp;
    k -= temp;
    c = k - a - b;
    if(k < N + M) return false;
    if(Y % X) {
        A = max(0LL, A - b);
        B = max(0LL, B - a);
        if(B + A > c) return false;
    } else {
        B = max(0LL, B - a);
        if(B + A > c) return false;
    }
    return true;
}
int main() {
//    freopen("input.txt", "r", stdin);
    while(~scanf("%I64d %I64d %I64d %I64d", &N, &M, &X, &Y)) {
        LL low = N + M, high = INF, mid;
        while (high >= low) {
            mid = (high + low) >> 1LL;
            if(check(mid)) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        printf("%I64d\n", low);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值