1. 程式人生 > >Codeforces 483B - Friends and Presents - [二分]

Codeforces 483B - Friends and Presents - [二分]

題目連結:https://codeforc.es/problemset/problem/483/B

You have two friends. You want to present each of them several positive integers. You want to present $cnt_1$ numbers to the first friend and $cnt_2$ numbers to the second friend. Moreover, you want all presented numbers to be distinct, that also means that no number should be presented to both friends.

In addition, the first friend does not like the numbers that are divisible without remainder by prime number $x$. The second one does not like the numbers that are divisible without remainder by prime number $y$. Of course, you're not going to present your friends numbers they don't like.

Your task is to find such minimum number $v$, that you can form presents using numbers from a set $1, 2, ..., v$. Of course you may choose not to present some numbers at all.

A positive integer number greater than $1$ is called prime if it has no positive divisors other than $1$ and itself.

Input
The only line contains four positive integers $cnt_1, cnt_2, x, y (1 \le cnt1, cnt2 < 10^9; cnt1 + cnt2 \le 10^9; 2 \le x < y \le 3·10^4)$ — the numbers that are described in the statement. It is guaranteed that numbers $x, y$ are prime.

Output
Print a single integer — the answer to the problem.

Examples
input
3 1 2 3
output
5
input
1 3 2 3
output
4

Note
In the first sample you give the set of numbers {1, 3, 5} to the first friend and the set of numbers {2} to the second friend. Note that if you give set {1, 3, 5} to the first friend, then we cannot give any of the numbers 1, 3, 5 to the second friend.

In the second sample you give the set of numbers {3} to the first friend, and the set of numbers {1, 2, 4} to the second friend. Thus, the answer to the problem is 4.

 

題意:

現在要給兩個人贈送一些正整數,要給第一個人送 $cnt_1$ 個正整數,要給第二個人送 $cnt_2$ 個正整數,且第一個人不想要能被 $x$ 整除的數,第二個人不想要能被 $y$ 整除的數。

現在你要求出最小的正整數 $v$,意味著你送出的正整數全部屬於 $1 \sim v$。

 

題解:

二分倒是不難想到,就是算怎麼給兩人整數不太好想。

舉個栗子:假設我現在 $v=7,x=2,y=3,cnt_1=3,cnt_2=3$,顯然此時能給第一個人的數字有 $1,3,5,7$,能給第二個人的數字有 $1,2,4,5,7$;

那麼我們知道,為了儘量使得 $v$ 小,我們應該儘量把第二個人不要的數字塞給第一個人,比如第二個人是不要 $3$ 的,但第一個人要,所以可以塞給他;同理,第一個人不要 $2,4$,但是第二個人要,可以塞給他;

假設 $1 \sim v$ 中能被 $x$ 整除的數有 $cnt_x$ 個,能被 $y$ 整除的數有 $cnt_y$ 個,能被 $xy$ 整除的數有 $cnt_xy$ 個;因此,第二個人不要而第一個人要的數字,其數量為 $cnt_y - cnt_xy$,第一個人不要而第二個人要的數字,其數量為 $cnt_x - cnt_xy$;

那麼剩下來再要送出去的數字,就既不能被 $x$ 整除,也不能被 $y$ 整除了,如果這些數夠分,那麼 $v$ 就是可行的,不夠分的話 $v$ 就不可行。

 

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
int cnt1,cnt2,x,y;

int judge(int v)
{
    int cnt_x=v/x, cnt_y=v/y, cnt_xy=v/(x*y);
    int rest1=max(cnt1-(cnt_y-cnt_xy),0);
    int rest2=max(cnt2-(cnt_x-cnt_xy),0);
    return rest1+rest2<=v-cnt_x-cnt_y+cnt_xy;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin>>cnt1>>cnt2>>x>>y;
    int l=1, r=2*(cnt1+cnt2);
    while(l<r)
    {
        int mid=l+(r-l)/2;
        if(judge(mid)) r=mid;
        else l=mid+1;
    }
    cout<<l<<'\n';
}