员工派遣(200)
- 员工工号连续,且从1开始;
- 从工号1-k中选择员工 派去 x国(需要nx人)、y国(需要ny人);
- 工号为x倍数的不去x国,工号为y倍数的不去y国;
- 找到最小的k,使得可以将编号1-k中的员工分配给x国、y国,且满足两国需求;
输入描述:
四个整数x,y,nx,ny;
2<x<y<30000,且x、y均为质数
1<nx,ny < 10^9
nx + ny <= 10^9
输出描述:
满足条件的最小的k
示例1
输入:2 3 3 1
输出:5
输入:177 431 2000 100000000
输出:100232558
解题思路
这题首先想到的就是暴力计算,代码很简单,数据太大会超时,第二个用例2s,要求要1s。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int x = sc.nextInt();
int y = sc.nextInt();
int cx = sc.nextInt();
int cy = sc.nextInt();
int shareNum = 0; //存储公共的数据
int nx =0; // 只能放入x的数据
int ny =0; // 只能放入y的数据
int curIndex =1;
for(int i=1;;i++) {
if(i%x!=0 && i%y!=0) {//既可以放入x又可以放入y,则放入公共里面
shareNum +=1;
}else if(i%x!=0) {
if(nx< cx) {
nx +=1;
}
}else if(i%y!=0) {
if(ny< cy) {
ny +=1;
}
}
if(nx+ny+shareNum == cx+cy) {
curIndex = i;
break;
}
}
System.out.println(curIndex);
}
}
二分查找,
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int x = sc.nextInt();
int y = sc.nextInt();
int cx = sc.nextInt();
int cy = sc.nextInt();
long min =1;
long max = (long)Math.pow(10, 9);
while(true) {
if(min >= max)break;
long mid = (min + max) >> 1;
/*1-k之间的数全部由这4类数组成: k/x=能除近x的个数, k/y=能出尽y的个数, k/(x*y)=xy的公倍数个数
剩下既不能出尽x也不能出尽y的个数 k- k/x -k/y + k/(x*y)*/
long target = Math.max(0, cx - (long)mid / y + (long)mid / (x * y))
+ Math.max(0, cy - (long)mid / x + (long)mid / (x * y));
if(mid - (long)mid / x - (long)mid / y + (long)mid / (x * y) >= target) {
max = mid;
}else {
min = mid+1;
}
}
System.out.println(min);
}
}