zoukankan      html  css  js  c++  java
  • 国王游戏

    国王游戏

    有一个长度为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();
    }
    
  • 相关阅读:
    OPPO R9sPlus MIFlash线刷TWRP Recovery ROOT详细教程
    OPPO R11 R11plus系列 解锁BootLoader ROOT Xposed 你的手机你做主
    努比亚(nubia) M2青春版 NX573J 解锁BootLoader 并进入临时recovery ROOT
    华为 荣耀 等手机解锁BootLoader
    青橙 M4 解锁BootLoader 并刷入recovery ROOT
    程序员修炼之道阅读笔03
    冲刺8
    典型用户模板分析
    学习进度八
    冲刺7
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11217333.html
Copyright © 2011-2022 走看看