zoukankan      html  css  js  c++  java
  • test20181015 B君的第二题

    题意


    分析

    考场85分

    用multiset暴力,由于教练的机子飞快,有写priority_queue水过了的人。

    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<ctime>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<list>
    #include<deque>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<bitset>
    #include<algorithm>
    #include<complex>
    #pragma GCC optimize ("O0")
    using namespace std;
    template<class T> inline T read(T&x)
    {
        T data=0;
    	int w=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
    		if(ch=='-')
    			w=-1;
    		ch=getchar();
    	}
        while(isdigit(ch))
            data=10*data+ch-'0',ch=getchar();
        return x=data*w;
    }
    typedef long long ll;
    const int INF=0x7fffffff;
    
    const int MAXN=1e5+7;
    int p[MAXN];
    
    struct node
    {
    	double pri;
    	int id,num;
    	
    	node(double pri=0,int id=0,int num=0):pri(pri),id(id),num(num){}
    	
    	bool operator<(const node&rhs)const
    	{
    		return pri > rhs.pri || (pri == rhs.pri && id < rhs.id);
    	}
    };
    multiset<node>H;
    multiset<node>::iterator it;
    
    int cnt[MAXN];
    
    int main()
    {
      freopen("taiyuan.in","r",stdin);
      freopen("taiyuan.out","w",stdout);
    	int n,m;
    	read(n);read(m);
    	for(int i=1;i<=n;++i)
    	{
    		read(p[i]);
    		H.insert(node(p[i],i,1));
    	}
    	node t;
    	for(int i=1;i<=m;++i)
    	{
    		it=H.begin();
    		t=*it;
    		H.erase(it);
    		++cnt[t.id];
    		t.pri=(double)p[t.id]/(++t.num);
    		H.insert(t);
    	}
    	for(int i=1;i<=n;++i)
    	{
    		printf("%d
    ",cnt[i]);
    	}
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    

    标解

    对于满分来说,关键在于直接算。

    那么如果不考虑精度问题,我们可以直接实数二分当选的票数,计算出有多少人当选,最后处理一下票数相同的情况。很遗憾这个方法的精度几乎一定会爆炸。

    最终的解法大概是,对于票数最多的党,整数二分这个党当选了多少人。
    用这个人数最多的党,去推别的党当选了多少人。
    这样推出来的结果,最多差1。
    最后贪心下。

    标程中的⽅法是直接虚拟一个党有10000 票,然后开始二分。

    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<ctime>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<list>
    #include<deque>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<bitset>
    #include<algorithm>
    #include<complex>
    #pragma GCC optimize ("O0")
    using namespace std;
    template<class T> inline T read(T&x)
    {
        T data=0;
    	int w=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
    		if(ch=='-')
    			w=-1;
    		ch=getchar();
    	}
        while(isdigit(ch))
            data=10*data+ch-'0',ch=getchar();
        return x=data*w;
    }
    typedef long long ll;
    const int INF=0x7fffffff;
    
    const int MAXN=1e5+7;
    int n,m;
    int p[MAXN];
    int z[MAXN];
    const int Q=1e4;
    
    ll calc(ll t)
    {
    	ll res=0;
    	for(int i=0;i<n;++i)
    	{
    		res+=p[i]*t/Q;
    		res=min(res,(ll)1e18);
    	}
    	return res;
    }
    
    struct node
    {
    	int x,y;
    	int id;
    	
    	node()=default;
    	
    	node(int x,int y,int id):x(x),y(y),id(id){}
    	
    	bool operator<(const node&rhs)const
    	{
    		if((ll)x*rhs.y!=(ll)y*rhs.x)
    		{
    			return (ll)x*rhs.y>(ll)y*rhs.x;
    		}
    		return id<rhs.id;
    	}
    };
    
    int main()
    {
      freopen("taiyuan.in","r",stdin);
      freopen("taiyuan.out","w",stdout);
    	read(n);read(m);
    	for(int i=0;i<n;++i)
    	{
    		read(p[i]);
    	}
    	
    	ll L=0,R=1e13;
    	while(L<R-1)
    	{
    		ll M=(L+R)/2;
    		if(calc(M)<=m)
    			L=M;
    		else 
    			R=M;
    	}
    	
    	int t=m-calc(L);
    	vector<node>V;
    	for(int i=0;i<n;++i)
    	{
    		z[i]=p[i]*L/Q;
    		if(p[i]*L/Q!=p[i]*R/Q)
    		{
    			V.push_back(node(p[i],z[i]+1,i));
    		}
    	}
    	sort(V.begin(),V.end());
    	for(int i=0;i<t;++i)
    	{
    		++z[V[i].id];
    	}
    	
    	for(int i=0;i<n;++i)
    	{
    		printf("%d
    ",z[i]);
    	}
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    

    解释一下,由于实数二分的精度问题,我们假设二分的实数为(frac{Q}{t}),那么当选人数为:

    [sum_{i} p_i / frac{Q}{t} = sum_{i} p_i * t / Q ]

    然后改为二分这个(t)

    静渊以有谋,疏通而知事。
  • 相关阅读:
    蛇形填数
    开灯问题
    水仙花数
    C++Primer笔记-----day02
    C++Primer笔记-----day01
    面试智力题
    maven 打包197
    子系统 安装vsftpd197
    office 安装破解197
    oracle 创建多个数据库197
  • 原文地址:https://www.cnblogs.com/autoint/p/9795848.html
Copyright © 2011-2022 走看看