Codeforces Round #275 (Div. 2) B. Friends and Presents

来源:互联网 发布:睡眠多久知乎 编辑:程序博客网 时间:2024/05/20 13:08

题目链接:http://codeforces.com/contest/483/problem/B

题目大意就是求一个最小的v,使得在集合 1.2.3.....v中,有cnt1个数字不能被x整除,有cnt2个数字不能被y整除,且前后cnt1个数字不能和cnt2个数字有重复的出现。

这是一道很有技巧性的题目,至少我是没见过,能想到就很简单,想不到就根本没思路。

首先要知道得二分,因为v要找最小的,所以二分是个很好的方法。

然后约束条件是很难想到的,在这里我们用到的是这么一个结论:在1-n中,有n-n/x个数不能被x整除,比如n=7,那么1-7中不能被2整除的有7-7/2=4个,即1,3,5,7。

所以每当我们二分到一个mid值,那么在1-mid这个范围内,就有mid-mid/x个不能被x整除的数,同理,有mid-mid/y个不能被y整除的数,但还有一点要注意,前后是不能有重复的,这个很关键,比如6,它既可以被2整除,也可以被3整除,那么怎么去除重复那?就是求出1-n个数中有多少不能同时被x和y整除的数,即mid-mid/(x*y),这个结果就是1-mid中,不重复的可以使用的数字的数目,那么符合条件的mid就是 cnt1<=mid-mid/x && cnt2<= mid-mid/y && cnt1+cnt2 <= mid-mid/(x*y)。

/* * ThinkingLion.cpp * *  Created on: 2014年10月2日 *      Author: dell */#include<stdio.h>#include<iostream>#include<string>#include<string.h>#include<algorithm>#include<iomanip>#include<vector>#include<time.h>#include<queue>#include<stack>#include<iterator>#include<math.h>#include<stdlib.h>#include<limits.h>#define eps 1e-8#define INF 0x7fffffff#define FOR(i,a) for((i)=0;i<(a);(i)++)#define MEM(a) (memset((a),0,sizeof(a)))#define sfs(a) scanf("%s",a)#define sf(a) scanf("%d",&a)#define sfI(a) scanf("%I64d",&a)#define pf(a) printf("%d\n",a)#define pfI(a) printf("%I64d\n",a)#define pfs(a) printf("%s\n",a)#define sfd(a,b) scanf("%d%d",&a,&b)#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)#define for1(i,a,b) for(int i=(a);i<b;i++)#define for2(i,a,b) for(int i=(a);i<=b;i++)#define for3(i,a,b)for(int i=(b);i>=a;i--)#define MEM1(a) memset(a,0,sizeof(a))#define MEM2(a) memset(a,-1,sizeof(a))const double PI=acos(-1.0);template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}template<class T> inline T Min(T a,T b){return a<b?a:b;}template<class T> inline T Max(T a,T b){return a>b?a:b;}using namespace std;#define N 100005#define maxn 220#define ll __int64int n,k;ll l,r;ll cnt1,cnt2,x,y;int main(){#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);#endifwhile(scanf("%I64d%I64d%I64d%I64d",&cnt1,&cnt2,&x,&y)!=EOF){l = 1,r=2e9;while(l<r){ll mid=(l+r)>>1;ll cx =mid-mid/x;ll cy=mid-mid/y;ll ctotal = mid-mid/(x*y);if(cnt1<=cx && cnt2 <=cy && cnt1+cnt2<=ctotal)r=mid;elsel=mid+1;}printf("%I64d\n",r);}return 0;}


0 0
原创粉丝点击