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