[NOIP2012TG]羅区P1080キングスゲーム

問題の意味

二つの等しい長さの配列を与えられた\(A [N-]、B [N-] \) および整数\(A、B \) の位置を逆転させることにより、

\ [\ MAX_ {i = 1} ^ {n}は{\ biggl \ lfloor \ FRAC {(\回\ prod_ {J = 1} ^ {I-1} a_iを)} {b_i} \ biggr \ rfloor} \クワッド(b_i \で\ mathbb {N +} FORALL \ a_iをFORALL、\)\]

最小。

分析

より重新安排顺序容易に理解、それはソートが必要です。これは、貪欲なアイデアで話題を分析貪欲な基準を見つけるために私たちを必要とします。

入手しやすい知識バブルソートでOシーケンスは、注文した商品を交換することができます。
そして、同じ効果のバブルソートやクイックソートは、ソート後に直接解決することができます。

だから我々は、貪欲、共通のアイデアを使用します。2つの要素のみの場合を考えますもちろん、それは私と私は同じ用語の効果の1を+列項目が、書き込みの不便として表現されます。

すなわち、二つの要素である(I、Jの\クワッド(\ J = I + 1)\) の大小関係は任意に拡張することができる\(I、Jの\クワッド( I <jの)\)

レンマ

とき\(X> 0 \)とき:

  • \(\ MAX(a、b)は\倍X = \ MAX(AX、BX)\)

証明するのは非常に簡単。

証明します

要素が設けられている((A1、B1)、(A2、B2)\)\賞それぞれ、\(M、N- \)が、

\ [M = \ FRAC {A} {B_1} \]

\ [N = \ FRAC {\時間A_1} {B_2} \]

交換がされた後

\ [M '= \ FRAC {A} {B_2} \]

\ [N '= \ FRAC {\時間A_2} {B_1} \]

条件は、交換する必要があります

\ [\ MAX(M、N)> MAX(M 'N')\ \]

収まります

\ [\ MAX(\ FRAC {A} {B_1}の\ FRAC {\時間A_1} {B_2})> MAX(\ \ FRAC {A} {B_2}の\ FRAC {\時間A_2} {B_1} )\]

さらに簡素化

不要

同時に両側\(\ FRAC {b_1b_2} { A} \)

\ [\ MAX(B_2、a_1b_1)> \ MAX(B_1、a_2b_2)\]

  • \(B_2 <a_1b_1、B_1 <
    a_2b_2 \) の直接比較\(a_1b_1、a_2b_2 \)サイズ

  • とき(B_2> a_1b_1、B_1 <\ a_2b_2 \) の時間を
    、そこにする必要があります(a_1b_1 <B_2 <a_2b_2 \)\直接比較に相当するものは、(a_1b_1、a_2b_2 \)\

  • (B_2 <a_1b_1、B_1> a_2b_2 \)\ 時間
    、同

  • 場合(B_2> a_1b_1、B_1 a_2b_2 \ >)\ 時間
    に関係なく\(B_2、B_1 \)サイズとの関係は、作製することができる方法(A_1、A_2 \で\ mathbb {N +} \)\の起動矛盾。

要約すると、とき

\ [a_1b_1> a_2b_2 \]

、あなたは交換する必要があります。

即ち、に従って\(a_ib_i \)の昇順に配列されています。

コード

これは、高精度を使用する必要があります

この文は、実際には、この問題のデバッグのコアがあり、簡単に話を聞きました。私はリロードするために使用しました

#include<algorithm>
#include<cstdio>
using namespace std;
const int MAXN=1005,MAXDIGIT=5005;
int n,ak,bk;
struct LongInt
{
    short num[MAXDIGIT];
    int d;
};
struct person
{
    int a;
    int b;
}s[MAXN];
LongInt temp,ans;

inline LongInt read()
{
    LongInt temp,ret;
    temp.d=ret.d=0;
    char c=getchar();
    while(c<'0'||c>'9');
    while(c>='0'&&c<='9')
    {
        temp.num[++temp.d]=c-'0';
        c=getchar();
    }
    for(int i=temp.d;i>=1;i--)
        ret.num[++ret.d]=temp.num[i];
    return ret;
}

inline void write (LongInt x)
{
    for(int i=x.d;i>=1;i--)
        putchar(x.num[i]+'0');
}

LongInt operator + (LongInt n1,LongInt n2)
{
    LongInt ret;
    int len=max(n1.d,n2.d)+1;
    for(int i=1;i<=len;i++)
    {
        ret.num[i]=0;
        if(i<=n1.d)
            ret.num[i]+=n1.num[i];
        if(i<=n2.d)
            ret.num[i]+=n2.num[i];
        ret.num[i+1]+=(ret.num[i]/10);
        ret.num[i]%=10;
    }
    while(!ret.num[len]) len--;
    ret.d=len;
    return ret;
}

LongInt operator * (LongInt n1,LongInt n2)
{
    LongInt ret;
    int l1=n1.d,l2=n2.d;
    ret.d=n1.d+n2.d;
    for(int i=1;i<=l1;i++)
        for(int j=1;j<=l2;j++)
            ret.num[i+j-1]=0;
    for(int i=1;i<=l1;i++)
    {
        for(int j=1;j<=l2;j++)
        {
            ret.num[i+j-1]+=n1.num[i]*n2.num[j];
            ret.num[i+j]+=ret.num[i+j-1]/10;
            ret.num[i+j-1]%=10;
            
        }
    }
    while(!ret.num[ret.d]) ret.d--;
    return ret;
}

LongInt operator / (LongInt n1,int n2)
{
    int r=0,len=n1.d;
    for(int i=len;i>0;i--)
    {
        r*=10;
        r+=n1.num[i];
        n1.num[i]=r/n2;
        r%=n2;
    }
    while(!n1.num[n1.d]) n1.d--;
    return n1;
}

bool operator < (LongInt n1,LongInt n2)
{
     if(n1.d!=n2.d) return n1.d<n2.d;
     for(int i=n1.d;i>=1;i--)
          if(n1.num[i]!=n2.num[i]) return n1.num[i]<n2.num[i];
}

LongInt trans (int x)
{
    LongInt ret;
    ret.d=0;
    while(x)
    {
        ret.num[++ret.d]=x%10;
        x/=10;
    }
    return ret;
}

int comp(person p1,person p2)
{
    return p1.a*p1.b<p2.a*p2.b;
}

int main()
{
    scanf("%d",&n);
    scanf("%d%d",&ak,&bk);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&s[i].a,&s[i].b);
    sort(s+1,s+1+n,comp);
    temp=trans(ak);
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,temp/s[i].b);
        temp=temp*trans(s[i].a);
    }
    write(ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/ehznehc/p/11609196.html