国王游戏

Posted a1b3c7d9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了国王游戏相关的知识,希望对你有一定的参考价值。

国王游戏

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

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

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

\[\max(\fraca_1a_2...a_i-1b_i,\fraca_1a_2...a_i-1a_ib_i+1)\]

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

\[\max(\fraca_1a_2...a_i-1b_i+1,\fraca_1a_2...a_i-1a_i+1b_i)\]

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

\[\max(\frac1b_i,\fraca_ib_i+1)\]

\[\max(\frac1b_i+1,\fraca_i+1b_i)\]

显然分式不好比较,同时乘一个\(b_ib_i+1\),于是就是比较

\[\max(b_i+1,a_ib_i),\max(b_i,a_i+1b_i+1)\]

注意到\(a_ib_i\geq b_i,a_i+1b_i+1\geq b_i+1\),于是即比较

\[a_ib_i,a_i+1b_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('\n');
    
    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();

以上是关于国王游戏的主要内容,如果未能解决你的问题,请参考以下文章

1198 国王游戏

CODEVS 1198 国王游戏

国王游戏

[Daimayuan]新国王游戏(C++,数学)

[Noip2012] 国王游戏

[NOIp 2012]国王游戏