B. Business Center

Problem B. Business Center

Input file: business.in

Output file: business.out

International Cyber Police Corporation (ICPC) had built a new mega-tall business center to host its headquarters and to lease some space for extra profit. It has so many floors, that it is impractical to have a separate button in each of itsmelevator cars for each individual floor. Instead, each elevator car has just two buttons. One button ini-th elevator car makes it move upuifloors, the other makes it move downdifloors. The business center is so high, that we can ignore its height for this problem (you will never reach the top floor), but you cannot go below the ground floor. All floors are numbered by integer numbers starting from zero, zero being the ground floor.

You start on the ground floor of the business center. You have to choose one elevator car out ofmto ride on. You cannot switch elevators cars after that. What is the lowest floor above the ground floor you can get to after you press elevator car buttons exactlyntimes?

Input

The first line of the input file contains two integer numbers n and m (1 ≤ n ≤ 1000000, 1 ≤ m ≤ 2000) — the number of button presses and the number of elevator cars to choose from. The followingmlines describe elevator cars. Each line contains two integer numbersuianddi(1 ≤ ui, di≤ 1000).

Output

Write to the output file a single positive integer number — the number of the lowest floor above ground floor that can be reached by one ofmelevators after pressing its buttons exactlyntimes.

Sample input and output

business.in

 

business.out

10 3

15 12

15 4

7 12


13

    题意:给出几组数据,每组数据包含一个正数和一个负数与其总共被使用的次数,求最接近0(大于0)的和。最后输出最小值。

    解题思路:开始的时候真拿这个题目没办法,连着读了好几遍题,才明白是什么意思。然后我就想到了枚举法,这个题目的数据范围是2*10^8感觉可以赌一赌压界过。于是我就假设对于每一组数据,最开始的时候所有的次数都用在下行,然后再逐次累加上行,直到刚好大于0的那个结果,就是该组的最优解。于是就有了以下的AC代码

#include <iostream>
#include <stdio.h>
using namespace std;

int main()
{
    freopen("business.in","r",stdin);
    freopen("business.out","w",stdout);
    int times,test,mi=0x3f3f3f3f3f;
    scanf("%d%d",&times,&test);
    for(int i=0; i<test; i++)
    {
        int up,down;
        scanf("%d%d",&up,&down);
        int t=-down*times;
        for(int i=0; i<times; i++)
        {
            if(t>0) break;
            else t+=up+down;
        }
        if(t>0) mi=min(t,mi);
    }
    printf("%d\n",mi);
    return 0;
}

    开始的时候一直挂在第八组数据,仔细读了题后才知道,最后的结果不能是0。思路还算清晰,不过算法复杂度有点大,耗时也很长,大概有600多ms。后来跟其他组的队员讨论了后,意识到这个题目可以通过解方程写,总次数是知道的。我们设上行次数是up,下行次数是down,总次数是times,那么就有up+down=times。另外,位置的表达式可以写成ui*up-di*down,这个位置很显然是大于0的,所以,综合两个式子,我们能写出表达式up>=times*di/(ui+di),这里也不用考虑小数点,因为无论等不等于0,都要往前取整。用了数学公式后,目测时间会减少很多。以下是我的AC代码
#include <iostream>
#include <stdio.h>
using namespace std;

int main()
{
    freopen("business.in","r",stdin);
    freopen("business.out","w",stdout);
    int times,test,mi=23214561435;
    scanf("%d%d",&times,&test);
    for(int i=0; i<test; i++)
    {
        int up,down,t;
        scanf("%d%d",&up,&down);
        int x=times*down/(up+down)+1;
        t=(up+down)*x-times*down;
        if(t>0) mi=min(t,mi);
    }
    printf("%d\n",mi);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值