HNU2019 Summer Training 3 E. Rounding

Problem Description


You decided to stay an extra day in Paris visiting favorite places of Parisians around Télécom ParisTech. You want to collect information about these favorite places, but asking people to fill in surveys is less fun than coding. For this reason, you asked the Parisian Agency for Really Imprecise Surveys to do it for you. You sent them a list of the P places you were interested in.

After surveying exactly 10 000 persons and asking them their favorite place (among these P places), the agency has just sent you the results. All persons surveyed answered the question. Unfortunately, the agency rounded the percentage results to the nearest integer, using the following formula: result =⌊original_value+12⌋\lfloor original\_value+\frac{1}{2} \rfloororiginal_value+21. In particular, decimal values of .50 are rounded up.

But since 10 000 persons were surveyed, you should have been able to get percentage values precise to the second decimal. What a loss of precision! You want to know the range in which each original result could be.

Input

The input comprises several lines:
• The first line consists of an integer P.
• Each of the following P lines consists of the name of a place followed by an integer i, separated with a single space.

Limits

• 1 ≤ P ≤ 10 000;
• the name of a place is a string of between 1 and 20 characters among Latin alphabet letters
(‘A’ to ‘Z’ and ‘a’ to ‘z’) and the underscore character (‘_’);
• no two names are the same;
• 0 ≤ i ≤ 100.

Output

If the results given by the agency are not consistent, print a single line with the word IMPOSSIBLE. Otherwise the output should consist of P lines, each of them should consist of the name of a place followed by a single space and two numbers, the smallest and the largest percentage values that place could have had in the original results, as floating-point numbers with two decimals separated with a single space (each number must have at least one digit before the decimal point, even if it is 0, and exactly 2 decimals, even if the trailing ones are 0). The places must be in the same order as in the input.

Sample Input

4
Catacombes 32
Cite_Universitaire 22
Arenes_de_Lutece 26
Observatoire 19

Sample Output

Catacombes 31.53 32.49
Cite_Universitaire 21.53 22.49
Arenes_de_Lutece 25.53 26.49
Observatoire 18.53 19.49

Sample Input2

7
Aqueduc_Medicis 11
Parc_Montsouris 40
Place_Denfert 10
Hopital_Sainte_Anne 4
Butte_aux_cailles 20
Cite_florale 12
Prison_de_la_Sante 0

Sample Output2

Aqueduc_Medicis 11.06 11.49
Parc_Montsouris 40.06 40.49
Place_Denfert 10.06 10.49
Hopital_Sainte_Anne 4.06 4.49
Butte_aux_cailles 20.06 20.49
Cite_florale 12.06 12.49
Prison_de_la_Sante 0.06 0.49

遍历区间,不多说,代码一看就懂

AC Code:

/*
 * Copyright (c) 2019 Ng Kimbing, HNU, All rights reserved. May not be used, modified, or copied without permission.
 * @Author: Ng Kimbing, HNU.
 * @LastModified:2019-07-27 T 22:28:46.246 +08:00
 */

package ACMProblems.Summer2019.HNUSummer;

import java.text.DecimalFormat;

import static ACMProblems.ACMIO.*;

public class Rounding {
    //Code for IO has been omitted.
    private static int n;
    private static int IMPOSSIBLE = -0x3F3F3F3F;
    private static final int maxn = 10005;
    private static int zeroNum;
    private static int hundredNum;
    private static int sum;
    private static int left;
    private static int upper = IMPOSSIBLE;
    private static int lower = IMPOSSIBLE;
    private static int[] a = new int[maxn];
    private static String[] s = new String[maxn];
    private static DecimalFormat df = new DecimalFormat("0.00");

    private static void print(String name, double d1, double d2) {
        out.println(name + " " + df.format(d1) + " " + df.format(d2));

    }

    private static String keepTwo(double d) {
        d += 0.005;
        String s = Double.toString(d);
        if (s.contains("."))
            return s.substring(0, s.indexOf('.') + 3);
        else return s + ".00";
    }

    private static boolean judge() {
        if (n == 1) {
            if (a[0] == 10000) {
                upper = 0;
                lower = 0;
                return true;
            }
            return false;
        }
        if (n == hundredNum)
            return false;
        int canGetGreater = n - hundredNum;
        int canGetLess = n - zeroNum;
        assert canGetGreater > 0;
        assert canGetLess >= 0;
        for (int i = 49; i >= -50; i--) {
            int toBeShared = (left - i);
            if (toBeShared < 0) {
                int eachShares = -51;
                int extra = 0;
                //如果存在0, 那当然选0来尝试增加,这样可以腾出更多的来减小  分担这次“增加”
                if (zeroNum > 0)
                    extra = 1;
                //除了自己还有别人可以分担
                if (canGetLess + extra > 1)
                    eachShares = (int) Math.floor(1.0 * toBeShared / (canGetLess + extra - 1));
                if (eachShares < -50)
                    continue;
            }
            upper = i;
            break;
        }
        if (upper == IMPOSSIBLE)
            return false;
        //lower bound
        for (int i = -50; i <= 49; i++) {
            int toBeShared = (left - i);
            if (toBeShared > 0) {
                int eachShares = 50;
                //除了自己还有别人可以分担
                int foo = 0;
                if (hundredNum > 0)
                    foo = 1;
                if (canGetGreater + foo > 1)
                    eachShares = (int) Math.ceil(1.0 * toBeShared / (canGetGreater + foo - 1));
                if (eachShares > upper)
                    continue;
            }
            lower = i;
            break;
        }
        return lower != IMPOSSIBLE && lower <= upper;
    }

    private static double safe(double k) {
        if (k < 0)
            return 0;
        if (k > 100)
            return 100;
        return k;
    }

    public static void main(String[] args) throws Exception {
        n = nextInt();
        lower = IMPOSSIBLE;
        upper = IMPOSSIBLE;
        for (int i = 0; i < n; ++i) {
            s[i] = next();
            a[i] = nextInt();
            if (a[i] == 0)
                zeroNum++;
            else if (a[i] == 100)
                hundredNum++;
            a[i] *= 100;
            sum += a[i];
        }
        left = 10000 - sum;
        if (judge()) {
            for (int i = 0; i < n; ++i)
                print(s[i], safe(a[i] / 100 + lower / 100.0), safe(a[i] / 100 + upper / 100.0));
        } else
            out.println("IMPOSSIBLE");
        out.flush();
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值