hdu 4710 Balls Rearrangement

题目连接:4710 Balls Rearrangement


题目大意:给出N, A 和B。N 代表有N个球, 原本N个球放在旧的A个箱子里面, 后来又买了B个新的箱子, 求要将N个球转移到新的箱子中需要多少移动距离。 放球的原则是 序号为  x 的球要放在 x mod A(或者B)序号的箱子里, 对于每个球的移动距离为| a - b |。


解题思路:因为N的上限是10^9, 所有不能对每个数进行 abs(x % a - x % b)后取和, 我的做法进行了两个优化。

1、首先,t = a * b, 0 ~ t - 1的移动距离是等于  t ~ 2 * t - 1的移动距离, (不一定是a * b, 具体来说是a 和b的最小公倍数。

2、其次,对于两条分界线中间的数来说, 移动距离也是相同的。

例如 : 11 5 3

0 1 2 / 3 4 | 5 / 6 7 8 / 9 |10 11 |


注意要用long long ,读入输出最好用cin , cout。


#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
long long a, b;

long long solve(long long n) {
    long long moveA = a, moveB = b, t = 0, cur, sum = 0;
    while (1) {
	if (moveA > moveB) {
	    cur = abs((moveB - 1) % a - (moveB - 1) % b);
	    sum += cur * (moveB - t);
	    t = moveB;
	    moveB += b;
	}
	else if (moveA < moveB) {
	    cur = abs((moveA  - 1) % a - (moveA - 1) % b);
	    sum += cur * (moveA - t);
	    t = moveA;
	    moveA += a;
	}
	else {
	    cur = abs((moveA - 1) % a - (moveA - 1) % b);
	    sum += cur * (moveA - t);
	    t = moveA;
	    moveA += a;
	    moveB += b;
	}

	if (moveA > n && moveB > n) break;
    }
    sum += abs((n - 1) % a - (n - 1) % b) * (n - t);
    return sum;
}

int main() {
    int cas;
    long long n, cur;
    scanf("%d", &cas);
    while (cas--) {
	cin >> n >> a >> b;
	if (a == b)
	    printf("0\n");
	else {
	    cur = a * b;
	    long long sum = 0;
	    if (n / cur)    sum += solve(cur) * (n / cur);
	    if (n % cur)    sum += solve(n % cur);
	    cout << sum << endl;
	}
    }
    return 0;
}


你可能感兴趣的:(hdu 4710 Balls Rearrangement)