zoukankan      html  css  js  c++  java
  • HDU 4803 Poor Warehouse Keeper (贪心+避开精度)

    555555,能避开精度还是避开精度吧,,,,我们是弱菜。。

    Poor Warehouse Keeper

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1672    Accepted Submission(s): 463

    Problem Description
    Jenny is a warehouse keeper. He writes down the entry records everyday. The record is shown on a screen, as follow:
    There are only two buttons on the screen. Pressing the button in the first line once increases the number on the first line by 1. The cost per unit remains untouched. For the screen above, after the button in the first line is pressed, the screen will be:
    The exact total price is 7.5, but on the screen, only the integral part 7 is shown. Pressing the button in the second line once increases the number on the second line by 1. The number in the first line remains untouched. For the screen above, after the button in the second line is pressed, the screen will be:
    Remember the exact total price is 8.5, but on the screen, only the integral part 8 is shown. A new record will be like the following:
    At that moment, the total price is exact 1.0. Jenny expects a final screen in form of:
    Where x and y are previously given. What’s the minimal number of pressing of buttons Jenny needs to achieve his goal?
     
    Input
    There are several (about 50, 000) test cases, please process till EOF. Each test case contains one line with two integers x(1 <= x <= 10) and y(1 <= y <= 109) separated by a single space - the expected number shown on the screen in the end.
     
    Output
    For each test case, print the minimal number of pressing of the buttons, or “-1”(without quotes) if there’s no way to achieve his goal.
     
    Sample Input
    1 1 3 8 9 31
     
    Sample Output
    0 5 11
    Hint
    For the second test case, one way to achieve is: (1, 1) -> (1, 2) -> (2, 4) -> (2, 5) -> (3, 7.5) -> (3, 8.5)
     
    Source
     
    Recommend
    liuyiding
     

    一个机器,只有两个按钮,上面的按钮表示数量,下面的表示总价(只显示整数部分)

    开始的时候数量和总价都是1,单价为1,然后进行一些操作,让数量变成x,总价变成y,求得是最小操作次数。

    如果按数量键,表示增加一个物品,单价不变,数量+1,那么总价=总价/数量*(数量+1),并且显示新的数量

    如果按总价键,单价=(总价+1)/数量,那么总价=总价+1,并且显示总价的整数部分。

    x很小y很大,暴力宽搜TLE了。

    换个角度,求最小操作次数 换成  求最小合法单价的操作次数

    因为最终得到了x数量,y的总价,对于一个单价tp,如果tp*x的整数部分==y那么这个单价就是可以的。

    而最小操作次数一定是 得到最小合法单价的操作次数。

    对于两种操作,按数量键并不会影响单价,按总价键会增加单价,而且增加单价的幅度是随着操作次数增多而下降的,按下数量键会是这个幅度下降的更多。

    这样,一共要按下x-1次数量键,每次按数量键前尽量多的按总价键(保证该单价下的x个数量物品不会超过y元),最后会得到一个不超过目标单价(y/x)的最大单价z,该单价下的总价值为z*n如果z*n<y则还需要按下若干次总价键。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #include<map>
     9 #include<set>
    10 #include<string>
    11 //#include<pair>
    12 
    13 #define N 1005
    14 #define M 1000005
    15 #define mod 1000000007
    16 #define inf 0x3f3f3f3f
    17 //#define p 10000007
    18 #define mod2 100000000
    19 #define ll long long
    20 #define LL long long
    21 #define maxi(a,b) (a)>(b)? (a) : (b)
    22 #define mini(a,b) (a)<(b)? (a) : (b)
    23 
    24 using namespace std;
    25 
    26 ll mul=3628800;
    27 ll x,y;
    28 ll ans;
    29 ll tmi,tma;
    30 ll dmi,dma;
    31 ll dan;
    32 ll num,tot;
    33 
    34 void ini()
    35 {
    36     ans=0;
    37     tmi=y*mul;
    38     tma=(y+1)*mul;
    39     dmi=tmi/x;
    40     dma=tma/x;
    41     num=1;
    42     dan=mul;
    43     tot=mul;
    44 }
    45 
    46 
    47 void solve()
    48 {
    49     ans=x-1;
    50     ll k1,k2;
    51     ll te;
    52     if(dan>=dma){
    53         ans=-1;return;
    54     }
    55     for(num=1;num<=x;num++){
    56         te=mul/num;
    57         if(dan>=dmi) break;
    58         k1=(dmi-dan+te-1)/te;
    59         k2=(dma-dan+te-1)/te;
    60       //  printf(" num=%I64d ans=%I64d dan=%I64d dmi=%I64d dma=%I64d te=%I64d k1=%I64d k2=%I64d
    ",
    61 //               num,ans,dan,dmi,dma,te,k1,k2);
    62         if(k1!=k2){
    63             ans+=k1;
    64             dan+=k1*mul/num;
    65             return;
    66         }
    67         else{
    68             dan+=(k1-1)*te;
    69             ans+=(k1-1);
    70         }
    71     }
    72 }
    73 
    74 void out()
    75 {
    76     printf("%I64d
    ",ans);
    77 }
    78 
    79 int main()
    80 {
    81     //freopen("data.in","r",stdin);
    82     //freopen("data.out","w",stdout);
    83     //scanf("%d",&T);
    84    // for(int ccnt=1;ccnt<=T;ccnt++)
    85    // while(T--)
    86     while(scanf("%I64d%I64d",&x,&y)!=EOF)
    87     {
    88         //if(n==0 && k==0 ) break;
    89         //printf("Case %d: ",ccnt);
    90         ini();
    91         solve();
    92         out();
    93     }
    94 
    95     return 0;
    96 }
  • 相关阅读:
    webstorm快捷键大全
    Js的reduce()方法
    利用 c# linq 实现多个数据库的联合查询
    微信小程序支付接入注意点
    ubuntu所有php扩展php-7.0扩展列表
    ubuntu 16.04 php 安装curl方法
    Ubuntu下配置Apache开启HTTPS
    Mac下如何用SSH连接远程Linux服务器及Linux一些常用操作命令,更新中.....
    Mac下如何用SSH连接远程Linux服务器
    C#的dapper使用
  • 原文地址:https://www.cnblogs.com/njczy2010/p/4028399.html
Copyright © 2011-2022 走看看