魔理沙的烟火制造

题目描述

在魔法森林,最有名的两个建筑物就是玛格特洛依德邸和雾雨邸。
这个问题便是雾雨邸的主人,雾雨魔理沙,在制造以星尘为原料的烟火时遇到的。
魔理沙一共想要制造T个烟火。她现在有n种星尘,用第i种材星尘制造一个烟火的花费为ci份星尘。由于同种星尘之间的排斥,每次用第i种星尘制造了一个烟火之后,下一次使用同种星尘制造一个烟火的花费会增加di。
幸运的是,魔理沙还有另外一种特别的,不会发生排斥的星尘。每次用这种星尘制造一个烟火,都要花费P份星尘。
收集星尘,即使是对于一个不需要借助任何物品就能飞行的人类而言,也不是一件容易的事。所以魔理沙想知道,制造所有的T个烟火,她至少要多少的星尘。

 

输入

第一行三个整数,代表T,P,n。
接下来n行,每行两个整数,代表ci,di。

 

输出

一行一个正整数代表答案。

样例输入

8 16 3
1 5
2 4
3 3

样例输出

43

提示

分别用1,2,3种星尘制造2,3,3个烟火,代价为1+6+2+6+10+3+6+9=43

 

 题解:

先用二分求出费用的上边界,由题目可得 初始值 l=0,r=p;

然后判断这个边界值取多少个,多了就减,少了就加。

AC代码:

 1 import java.util.*;
 2 import java.math.*;
 3 public class Main {
 4     static int n;
 5     static long t,p,sumx;
 6     static long[] a=new long[100005];
 7     static long[] b=new long[100005];
 8     static BigInteger ans=BigInteger.valueOf(0),ttt=BigInteger.valueOf(2);
 9     public static boolean check(long val) {
10         long sum=0;
11         for(int i=1;i<=n;i++) {
12             long res=a[i];
13             if(res<=val) {
14                 sum++;
15                 long ret=(val-res)/b[i];
16                 sum+=ret;
17                 if(sum>=t) return true;
18             }
19         }
20         return false;
21     }
22     public static void solve(long val) {
23         long sum=0;
24         for(int i=1;i<=n;i++) {
25             long res=a[i];
26             if(res<=val) {
27                 sum++;
28                 BigInteger tmp=BigInteger.valueOf(res);
29                 long ret=(val-res)/b[i];
30                 sum+=ret;
31                 BigInteger Ret=BigInteger.valueOf(ret);
32                 BigInteger cnt=tmp.add(Ret.multiply(BigInteger.valueOf(b[i])));
33                 ans=ans.add(cnt.add(tmp).multiply(Ret.add(BigInteger.valueOf(1))).divide(ttt));
34             }
35         }
36         sumx=sum;
37     }
38     public static void main(String args[]) {
39         Scanner cin=new Scanner(System.in);
40         t=cin.nextLong();
41         p=cin.nextLong();
42         n=cin.nextInt();
43         long ma=1000000000;
44         int pos=0;
45         boolean flag=false;
46         for(int i=1;i<=n;i++) {
47             a[i]=cin.nextLong();
48             if(a[i]==0) {
49                 flag=true;
50             }
51             b[i]=cin.nextLong();
52             if(ma>b[i]) {
53                 ma=b[i];pos=i;
54             }
55         }
56         if(t==0) {
57             System.out.println(0);
58             cin.close();
59             return ;
60         }
61         if(p==0) {
62             System.out.println(0);
63             cin.close();
64             return ;
65         }
66         if(b[pos]==0){
67             if(flag) {
68                 System.out.println(0);
69                 cin.close();
70                 return ;
71             }
72             else {
73                 System.out.println(t);
74                 cin.close();
75                 return ;
76             }
77         }
78         long l=0,r=p;
79         while(l<r) {
80             long mid=(l+r)/2;
81             if(check(mid)) r=mid;
82             else l=mid+1;
83         }
84         solve(l);
85         if(l==p) {
86             ans=ans.add(BigInteger.valueOf(p).multiply(BigInteger.valueOf(t-sumx)));
87         }
88         else {
89             ans=ans.subtract(BigInteger.valueOf(l).multiply(BigInteger.valueOf(sumx-t)));
90         }
91         System.out.println(ans.toString());
92         cin.close();
93     }
94 }
View Code

 

posted @ 2019-07-09 23:45  Gang_Li  阅读(173)  评论(0编辑  收藏  举报