【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;
}