zoukankan      html  css  js  c++  java
  • 【推导】【贪心】【高精度】Gym

    题意:每个队伍有个赔率pi,如果你往他身上押x元,它赢了,那么你得到x+(1/pi)x元,否则你一分都得不到。问你最多选几支队伍去押,使得存在一种押的方案,不论你押的那几支队伍谁赢,你都能赚得到钱。

    设你往第i支队伍上押ai元,不选的视作零元。

    首先可以证明,不论你持有多少钱,不影响最后是否有解;是否有解只跟你往各个队伍上押的比例有关。所以不妨设你持有的钱为常数A。

    于是有不等式ai*(1+1/pi)>=A,大胆猜测等号成立时,有最极限的解。于是ai=A/(1+1/pi)。

    也就是你往第i支队伍身上押的钱数,占你的总钱数的1/(1+1/pi)。

    于是把所有队伍按照1/(1+1/pi)从小到大排序,依次尽量选择即可。

    注意!由于精度爆炸,所以要用高精度做分数运算。

    import java.util.*;
    import java.io.*;
    import java.math.*;
    
    public class Main{
    	public static void main(String[] argc){
    		BigInteger[] A=new BigInteger[105];
    		BigInteger[] B=new BigInteger[105];
    		double[] C=new double[105];
    		int[] vis=new int[105];
    		String S;
    		char[] s=new char[105];
    		Scanner sc = new Scanner (new BufferedInputStream(System.in));
    		int T=sc.nextInt();
    		for(int zu=1;zu<=T;++zu){
    			System.out.printf("Case #%d: ",zu);
    			int n=sc.nextInt();
    			for(int i=1;i<=n;++i){
    				long tA=0,tB=0;
    				S=sc.next();
    				int len=S.length();
    				s=S.toCharArray();
    				int colon=0;
    				for(int j=0;j<len;++j){
    					if(s[j]==':'){
    						colon=j;
    						break;
    					}
    				}
    				int pos1=colon-1;
    				for(int j=0;j<colon;++j){
    					if(s[j]=='.'){
    						pos1=j;
    					}
    					else{
    						tA=tA*10+s[j]-'0';
    					}
    				}
    				int pos2=len-1;
    				for(int j=colon+1;j<len;++j){
    					if(s[j]=='.'){
    						pos2=j;
    					}
    					else{
    						tB=tB*10+s[j]-'0';
    					}
    				}
    				for(int j=1;j<=colon-pos1-len+pos2;++j){
    					tB*=10l;
    				}
    				for(int j=1;j<=len-pos2-colon+pos1;++j){
    					tA*=10l;
    				}
    				A[i]=BigInteger.valueOf(tA);
    				B[i]=A[i].add(BigInteger.valueOf(tB));
    				C[i]=(double)tA/((double)tA+(double)tB);
    			}
    			BigInteger sumA=BigInteger.ZERO,sumB=BigInteger.ONE;
    			for(int i=1;i<=n;++i){
    				vis[i]=0;
    			}
    			int flag=0;
    			for(int i=1;i<=n;++i){
    				double minn=2000000000.0;
    				int id=0;
    				for(int j=1;j<=n;++j)if(vis[j]==0){
    					if(C[j]<minn){
    						minn=C[j];
    						id=j;
    					}
    				}
    				vis[id]=1;
    				sumA=sumA.multiply(B[id]).add(sumB.multiply(A[id]));
    				sumB=sumB.multiply(B[id]);
    				if(sumA.compareTo(sumB)>=0){
    					System.out.println(i-1);
    					flag=1;
    					break;
    				}
    			}
    			if(flag==0){
    				System.out.println(n);
    			}
    //			for(int i=1;i<=n;++i){
    //				System.out.print(A[i]);
    //				System.out.printf(" ");
    //				System.out.println(B[i]);
    //			}
    		}
    		sc.close();
        }
    }
  • 相关阅读:
    关于String
    MySQL中count(1)、count(*) 与 count(列名) 的执行区别?
    OSC的原理
    [java] 模拟QPS
    [java] 简单的ConcurrentHashMap
    [java] 线程池
    [Guava] EventBus
    [jvm]垃圾回收算法
    [zookeeper] Zookeeper概述
    [NS2]TCL语言基本语法
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7667999.html
Copyright © 2011-2022 走看看