• 国王游戏


    国王游戏

    有一个长度为n的二元组数列((a_i,b_i)),定义一个位置i的权值为([frac{prod_{i=1}^{i-1}a_i}{b_{i}}])(显然(i>1)),现在允许你将后n-1个位置的顺序自由交换,询问权值的最大值的最小值,(nleq 1000)

    显然问题带有浓厚的二分性,但是二分无法判断是否能更优秀,自然倍增也萎掉了,如果使用递推,后面的问题类似全排列,你要么是二进制压缩记录选没选,要么是按照一个顺序,将数字填入序列,显然两者皆萎了,考虑递推兄弟贪心。

    考虑微扰法,考虑两个相邻位置(i,i+1)而言,显然这两个位置对答案的影响即(先不考虑向下取整,因为非向下取整得到的关系,考虑了向下取整后,最多是大于关系变成大于等于关系)

    [max(frac{a_1a_2...a_{i-1}}{b_i},frac{a_1a_2...a_{i-1}a_i}{b_{i+1}}) ]

    而交换了位置,对答案的影响即

    [max(frac{a_1a_2...a_{i-1}}{b_{i+1}},frac{a_1a_2...a_{i-1}a_{i+1}}{b_{i}}) ]

    显然,相同的项,不会影响大小比较,提出来,即比较

    [max(frac{1}{b_i},frac{a_i}{b_{i+1}}) ]

    [max(frac{1}{b_{i+1}},frac{a_{i+1}}{b_{i}}) ]

    显然分式不好比较,同时乘一个(b_ib_{i+1}),于是就是比较

    [max(b_{i+1},a_ib_i),max(b_i,a_{i+1}b_{i+1}) ]

    注意到(a_ib_igeq b_i,a_{i+1}b_{i+1}geq b_{i+1}),于是即比较

    [a_ib_i,a_{i+1}b_{i+1} ]

    到此,我们就发现只要二元组两个元的乘积只要前者小于后者,就意味着不交换比交换优秀,反之,显然只要交换者排序,也就是冒泡排序,就可以得到最优解。

    于是,根据冒泡排序的性质,容易知道,以(a_ib_i)为关键字进行冒泡排序,最终必然可以得到该个关键字的递增序列,也就是说,我们可以直接对这个关键字进行快速排序或者归并排序,(O(n))统计答案,然后就可以做到时间复杂度(O(nlogn))

    但是这道题要高精,也许我算出来的时间复杂度并不对?

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define il inline
    #define ri register
    #define lb long double
    #define Size 1500
    using namespace std;
    struct lll{
        int num[4250];
        il void clear(){
            memset(num,0,sizeof(num));
        }
        il lll(){
            clear(),num[0]=1;
        }
        il void print(){
            for(ri int i(num[0]);i;--i)
                putchar(num[i]+48);putchar('
    ');
        }
        template<class free>
        il void operator=(free x){num[0]^=num[0];
            do num[++num[0]]=x%10,x/=10;while(x);
        }template<class free>
        il void operator*=(free x){
            ri int i,j(0);
            for(i=1;i<=num[0]||j;++i)
                (num[i]*=x)+=j,j=num[i]/10,num[i]%=10;
            while(i>1&&!num[i])--i;num[0]=i;
        }
        il lll operator/(int x){
            lll y;ri int i,j(0);
            for(int i(num[0]);i;--i)
                j=j*10+num[i],
                    y.num[i]=j/x,j%=x;
            i=num[0];while(i>1&&!y.num[i])--i;
            return y.num[0]=i,y;
        }
        il bool operator<(lll x){
            if(num[0]<x.num[0])return true;
            if(num[0]>x.num[0])return false;
            for(ri int i(num[0]);i;--i)
                if(num[i]<x.num[i])return true;
                else if(num[i]>x.num[i])return false;
            return false;
        }
    }gzy,ans;
    struct inter{
        int l,r,key;
        il bool operator<(const inter&x){
            return key<x.key;
        }
    }I[Size];
    il void read(int&);
    int main(){
        int n;read(n),++n;
        for(int i(1);i<=n;++i)
            read(I[i].l),read(I[i].r),
                I[i].key=I[i].l*I[i].r;
        sort(I+2,I+n+1),gzy=I[1].l;
        for(int i(2);i<=n;gzy*=I[i].l,++i)
            if(ans<gzy/I[i].r)
                ans=gzy/I[i].r;
        ans.print();
        return 0;
    }
    il void read(int &x){
        x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
  • 相关阅读:
    [No000037]操作系统Operating Systems操作系统历史与硬件概况History of OS & Summaries!
    [No000036]操作系统Operating Systems系统调用的实现System_Call
    [No000035]操作系统Operating System之OS Interface操作系统接口
    [No000034]知乎-长期接收碎片化知识有什么弊端?
    [No000033]码农网-如何锻炼出最牛程序员的编码套路
    [No000032]程序员的年龄天花板
    [No000031]操作系统 Operating Systems 之Open the OS!
    [No000030]程序员节发点别的:中国教育整个把人脑子搞坏了-易中天
    [No00002F]3步,教你如何分解需求
    [No00002E]关于大数据,你不知道的6个迷思
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11217333.html
Copyright © 2020-2023  润新知