zoukankan      html  css  js  c++  java
  • 【YBTOJ】【Luogu P1080】国王游戏

    题目大意:

    两个数列 (a_i,b_i)。位置 (i) 的价值是 (frac{prod_{j=0}^{i-1}a_j}{b_i}),现在给两个数列 (a,b) 同时排列,问怎么排使得最大权值最小。

    正文:

    (s_i) 表示 (prod_{j=0}^{i}a_j),考虑贪心邻相交换:

    当前位置 (a) (b) 交换前权值
    (i) (a_i) (b_i) (frac{s_{i-1}}{b_i})
    (i+1) (a_{i+1}) (b_{i+1}) (frac{s_{i-1} imes a_i}{b_{i+1}})

    ( ext{ans}_1=max{frac{s_{i-1}}{b_i},frac{s_{i-1} imes a_i}{b_{i+1}}})

    交换后:

    当前位置 (a) (b) 交换后权值
    (i+1) (a_{i+1}) (b_{i+1}) (frac{s_{i-1}}{b_{i+1}})
    (i) (a_i) (b_i) (frac{s_{i-1} imes a_{i+1}}{b_i})

    ( ext{ans}_2=max{frac{s_{i-1}}{b_{i+1}},frac{s_{i-1} imes a_{i+1}}{b_i}})

    显然 (frac{s_{i-1}}{b_i}<frac{s_{i-1} imes a_{i+1}}{b_i})

    ( ext{ans}_1< ext{ans}_2),那么 (frac{s_{i-1} imes a_i}{b_{i+1}}<frac{s_{i-1} imes a_{i+1}}{b_i})

    对这个式子变形:

    [egin{aligned}frac{s_{i-1} imes a_i}{b_{i+1}}&<frac{s_{i-1} imes a_{i+1}}{b_i}\ s_{i-1} imes a_i imes b_i&<s_{i-1} imes a_{i+1} imes b_{i+1}\ a_i imes b_i&<a_{i+1} imes b_{i+1} end{aligned}]

    也就是说,答案尽量小的话,(a_i imes b_i) 必须小,那就按这个为 key 对它们排序。

    接下来就更简单了,枚举 (i) 的权值,取个最大就行啦!

    由于本题很毒瘤,所以开个高精度。

    代码:

    const int N = 1010;
    
    struct node
    {
    	int a[50010];
        int &operator [](int x){return a[x];}
    	node()
    	{
    		memset (a, 0, sizeof a);
    	}
    	inline void print()
    	{
    		for (int i = a[0]; i >= 1; i--)
    			printf ("%d", a[i]);
    	}
    }ans, tool;
    
    node operator * (node A, ll a)  
    {
    	int s = 0, g = 0;
    	node C;
    	int len = A[0];
    	for (int i = 1; i <= len + 10; i++)
    	{
    		s = A[i] * a + g, g = s / 10;
    		C[i] = s % 10;
    		if (!s && !g && i > len) break;
    		C[0] = i; 
    	}
    	return C;
    }
    
    node operator / (node A, ll a)  
    {
    	int s = 0;
    	node C;
    	C[0] = A[0];
    	for (int i = A[0]; i; i--)
    	{
    		s = s * 10 + A[i];
    		C[i] = s / a, s %= a;
    	}
    	while (!C[C[0]] && C[0] > 1) --C[0];
    	return C;
    }
    
    node Max (node a, node b)
    {
    	if (a[0] > b[0]) return a;
    	if (a[0] < b[0]) return b;
    	for (int i = a[0]; i >= 1; i--)
    	{
    		if (a[i] > b[i]) return a;
    		if (a[i] < b[i]) return b;
    	}
    	return a;
    }
    
    struct INp 
    {
    	ll x, y;
    }a[N];
    
    bool cmp (INp a, INp b)
    {
    	return a.x * a.y < b.x * b.y;
    }
    
    int n, m;
    
    int main()
    {
    	scanf ("%d", &n);
    	for (int i = 0; i <= n; i++)
    		scanf ("%lld%lld", &a[i].x, &a[i].y);
    	sort (a + 1, a + 1 + n, cmp);
    	tool[1] = tool[0] = 1;
    	for (int i = 1; i <= n; i++)
    	{
    		tool = tool * a[i - 1].x;
    		ans = Max(ans, tool / a[i].y);
    	}
    	ans.print();
        return 0;
    }
    
  • 相关阅读:
    《观止》读后感
    读产品经理相关书籍有感
    windows phone 7基础点随手记
    Windows phone 7画图画字
    《CLR via C#》读书笔记
    《Beginning C# Objcets》学习笔记
    ASP.NET 使用alert弹出对话框后,CSS样式失效,字体变大的解决方法
    .NET COOKIE /SESSION/CACHE操作类
    【原创】VS2005 Web应用程序打包并安装数据库
    存储过程实现多条件查询
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14185199.html
Copyright © 2011-2022 走看看