C语言--Friends and Present

题目链接:点击打开链接

Description

You have two friends. You want to present each of them several positive integers. You want to presentcnt1 numbers to the first friend andcnt2 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 numberx. The second one does not like the numbers that are divisible without remainder by prime numbery. Of course, you're not going to present your friends numbers they don't like.

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

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

Input

The only line contains four positive integerscnt1, cnt2, x,y (1 ≤ cnt1, cnt2 < 109;cnt1 + cnt2 ≤ 109;2 ≤ x < y ≤ 3·104) — the numbers that are described in the statement. It is guaranteed that numbersx, y are prime.

Output

Print a single integer — the answer to the problem.

Sample Input

Input
3 1 2 3
Output
5
Input
1 3 2 3
Output
4

Sample Output

Hint

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 numbers1, 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.


题目大意讲述的是一个人送他两朋友(假设为A B)数字,其中A不喜欢素数X,B不喜欢素数Y,所以送他们地数字不能是XY的倍数;输入有四个数字代表A不喜欢的数字,B不喜欢的数字;给出的一个范围的一边i ,j(分别针对A B );求一个最小数n满足i;j 与它构成的范围中有数满足·送数条件。


题目分析:这道题如果用暴力枚举的话肯定不可行,在网上和学长的指导下终于找到了一个实用简单的方法,进行二分查找。




要点及注意事项:这道题估计最简单的方法就是二分查找了;值得注意的就是二分上限,结合各数据大小分析可得。

AC代码----借鉴方法就可以了(二分查找)

大神的代码——--------------

#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
	int n,m,x,y,median;
	while(scanf("%d%d%d%d",&n,&m,&x,&y)!=EOF)
	{
		int l=2,ans=2e9+1;
		while(l<ans)
		{        
			median=l+ans/2;
			if(n<=(median-median/x)&&m<=(median-median/y)&&n+m<=median-median/(x*y))
				ans=median;
			else
				l=median+1;
		}
		printf("%d\n",ans);	
	}
	return 0;
} 



下面是我和同学们普遍的代码
运行状态(RTL)
#include<stdio.h>
int main()
{
    int cn1,cn2,i,j,x,y;//flag来标记x,y的公倍数
    while(scanf("%d%d%d%d",&cn1,&cn2,&x,&y)!=EOF){
        int n1=0,n2=0,flag=0;//n1,n2记录送给第一个人和第二个人数字的个数
        for(i=1;n1<cn1||n2<cn2;i++){//当n1和n2同时达到目标cn1,cn2时结束
            if(i%y!=0&&i%x!=0&&n1<cn1)
                flag++;
            if(i%x!=0&&n1<cn1)//当n1<cn1时,先保证第一个人达到要求
                n1++;
            else if(i%y!=0)
                n2++;
            else if(i%y==0&&i%x!=0&&flag>0){
                n2++;
                flag--;
            }
//当第一个人达到要求后出现了满足第一个人而不满足第二个人时,
//让第一个人用他满足第二个人又满足第一个人的数与第二个人交换。
<pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif;">//注意如果交换完了怎么办?</span>
} printf("%d\n",i-1); } return 0;}
 
    



心得:AC了这道题最大感悟就是,有时候可以把问题换个角度想下,比如二分就比暴力枚举更高效有力,暴力枚举一不小心就超时了




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值