SRM522

【div1】

 第一题和第二题通过系统测试,第三题没去做

下面是第三题思路:

First of all, notice that although a, b and c are bounded by the constraints, we do not really have any constraints for A, B or C other than they must be positive. This means that they may actually be higher than their counterparts, and we do not actually know how much larger. That is likely a good first step to try, to find good bounds for A,B and C. In problems that ask you to pick some numbers with a strong relation between each other, it is usually helpful to try to first fix one or more of them and try to find the best values for the remaining ones. In order to, for example, fix A, we will first need to iterate through all possible values of A, and for that, we need to estimate the maximum value of A we need to verify.

Instead of finding the bounds for A,B or C, let us first try to find an upper bound for the answer. The answer is equal to the minimum possible abs(A - a) + abs(B - b) + abs(C - c) - The sum of the distances between each of the original values and the new values. We need to find new values such that: A*B = C. The simplest positive multiplaction is 1*1 = 1. A possible result is always to set (A = B = C = 1). The final cost in this easy case is: (a - 1) + (b - 1) + (c - 1) = (a + b + c - 3). We will temporarily call this result res. res is going to be a variable that holds the best result found so far. It follows that no new result that we find should exceed res, because we want to improve the result not to make it worse. So, if we find an optimal result, it should not exceed (a + b + c - 3), so it will work as an upper bound for the result.

It is time to notice that the it is also true that C cannot be larger than (c + res). If C was larger than c + res, then abs(C - c) would be larger than res, and the final sum of distances will also be larger than res.

Knowing that C is at most (c + res), it should follow that A is at most (c + res) as well. Because we want A*B to be equal to C, if A was larger than the maximum value of C, it would be impossible for the product A*B to be exactly equal to C. In fact, we have that ( A*B <= c + res). Thus after fixing a value of A, we are only interested in values of B such that the product A*B would not exceed (c + res). We can now imagine the following solution:

int getMinimum(int a, int b, int c)
{
    // upper bound for the result:
    int res = a + b + c - 3;
    
    // C is at most (c + res).

    // A*B is at most (c + res).
    for (int A = 1; A <= c + res; A ++) {

        // A*B is at most (c + res).
        // to avoid doing the multiplication (and risk overflow),
        // we can check B <= (c + res)/A , instead of A*B <= c + res.
        //
        for (int B = 1; B <= (c + res)/A; B++) {
            // The  value of C has to be equal to A*B
            int C = A*B;
            
            // Verify the cost of the found values, is it the minimum
            // we have found so far? Update it.
            res = std::min(res, abs(A-a) + abs(B-b) + abs(C-c) );
        }
    }
    // Return the minimum value we have found.
    return res;
}

Faster solution

We can also be safer and think of more optimizations. Instead of picking pairs B after picking A, we will pick C and then B. Assuming that we pick the optimal B and C, how much will c differ from A * B = C ? What will follow is that C cannot be larger than (c + A) and cannot be smaller than (c - A): If we increased c by A, it would be easier to just increase B by 1. (At the end, A * (B + 1) = A*B + A ). Similarly, if we decreased c by A, it would be easier to decrease B by 1. Thus, we should try all values of C from (c - A) to (c + A). However, notice that B = C / A. If the new C was (c + x), (Where x can be negative and its absolute value is less than or equal to A). Then B = (c + x)/A = c/A + x/A. It does not matter what the value of x is, x/A will be a integer between -1 and 1, inclusive. So we will find that B can be equal to: (c/A -1), (c/A) or (c/A + 1). Those are only three values. The following algorithm is the direct result from that previous conclusion:

int getMinimum(int a, int b, int c)
{
    // upper bound for the result:
    int res = a + b + c - 3;
    
    // C is at most (c + res).

    // A*B is at most (c + res).
    for (int A = 1; A <= c + res; A ++) {
        // B is equal to c/A-1, c/A, or c/A +1
        for (int o=-1; o<=1; o++) {
            int B = c/A + o;
            if (B >= 1) {
                int C = A * B;
                // Verify the cost of the found values, is it the minimum
                // we have found so far? Update it.
                res = std::min(res, abs(A-a) + abs(B-b) + abs(C-c) );

            }
        }
    }
    // Return the minimum value we have found.
    return res;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值