【codeforces 483B】Friends and Presents

【链接】 我是链接,点我呀:)
【题意】

【题解】

我们可以二分n的值,设为mid 那么对于n=mid 我们可以算出来以下3个东西 temp1 = n/x; temp2 = n/y; temp3 = n/lcm(x,y);//lc(x,y)表示x和y的最小公倍数 temp1是第一个人在1..n中不喜欢的数的个数 temp2是第二个人在1..n中不喜欢的数的个数 temp3是两个人在1..n中都不喜欢的数的个数。 那么我们把1..n中temp1-temp3个第一个人不喜欢的数字全给第二个人 然后把1..n中temp2-temp3个第二个人不喜欢的数字全给第一个人 这样就能最大化地利用所有数字了。 然后 cnt[1]-=temp2-temp3 cnt[2]-=temp1-temp3 然后如果cnt[1]<0,cnt[1] = 0; 如果cnt[2]<0,cnt[2]=0; 然后cnt[1]+cnt[2]就是两个人还需要的数字的个数了. 然后n个数字还剩下n-temp1-temp2+temp3个数字。 这些数字是他们都能接受的。 那么看看cnt[1]+cnt[2]是不是小于等于那些剩余的数字就好了。 如果ok 那么就说明n=mid是可行的。 按照是否可行更改l和r的值就ok

【代码】

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

const int N = 1e4;

LL cnt[3],x,y;

bool ok(LL v){
    LL temp1 = v/x;
    LL temp2 = v/y;
    LL temp3 = v/(x*(y/__gcd(x,y)));
    LL tc1 = cnt[1],tc2 = cnt[2];
    tc1-=(temp2-temp3);
    tc2-=(temp1-temp3);
    if (tc1<0) tc1 = 0;
    if (tc2<0) tc2 = 0;
    LL rest = v-temp1-temp2+temp3;
    if (tc1+tc2<=rest) return true;
    return false;
}

int main()
{
    //freopen("D:\rush.txt","r",stdin);
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> cnt[1] >> cnt[2] >> x >> y;
    LL l = 1,r = 1e10,temp = -1;
    while(l<=r){
        LL mid = (l+r)>>1;
        if (ok(mid)){
            temp = mid;
            r = mid - 1;
        }else l = mid + 1;
    }
    cout<<temp<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/9742231.html