1. 程式人生 > >[NOIp2012] 國王遊戲(排序 + 貪心 + 高精度)

[NOIp2012] 國王遊戲(排序 + 貪心 + 高精度)

題意

給你兩個長為 \(n+1\) 的陣列 \(a,b\) ,你需要定義一個順序 \(p\)\(p_0\) 永遠為 \(0\)

能夠最小化
\[ \max_{i=1}^{n} \frac{\prod_{j = 0}^{i} a_{p_j}}{b_{p_i}} \]
\(1 \le n \le 1000, 1 \le a, b \le 10^4\)

題解

開始把原來沒做完的 \(NOIp\) 題都水掉qwq

類似這種題都需要有個巧妙的排序方法,使得答案最小,其實可以大力找規律或者猜結論發現按 \(a_i \times b_i\) 排序是最優秀的。

我們嘗試推導這個結論。

其實我們發現只需要考慮相鄰兩個數如何交換才是最優的,因為任意排列都可以由交換相鄰兩個數得到。

假設當前兩個位置為 \(i, i+1\) ,記 \(\displaystyle p = \prod_{j = 0}^{i - 1}a_j\)

我們令 \(ans_0\) 為交換前的最大值,\(ans_1\) 為交換後的,那麼有
\[ \begin{cases} ans_0 &= \max\{\frac{p}{b_i}, \frac{p \times a_i}{b_{i+1}}\} \\ ans_1 &= \max\{\frac{p}{b_{i+1}}, \frac{p \times a_{i+1}}{b_{i}}\} \end{cases} \]
因為有
\[ \forall i, a_i, b_i \ge 1 \]


不難發現有
\[ \begin{cases} \displaystyle \frac{p \times a_i}{b_{i+1}} \ge \frac{p}{b_{i+1}} \\ \displaystyle \frac{p \times a_{i+1}}{b_{i}} \ge \frac{p}{b_i} \end{cases} \]
所以當 \(ans_1 \ge ans_0\) 也就是交換後不會更優,當且僅當
\[ \begin{aligned} \frac{p \times a_{i+1}}{b_{i}} &\ge \frac{p \times a_i}{b_{i+1}} \\ a_{i + 1} \times b_{i + 1} &\ge a_i \times b_i \end{aligned} \]

所以我們不難發現當 \(a_i \times b_i\) 升序的時候是最優的。

然後答案需要用高精度儲存,但是我不想寫。。。(用 \(python\) 水過了2333)

考試時候應該還是會頭鐵寫高精度的。。

總結

對於重排序列使得一些要求的東西最優的時候,可以考慮不等式推導。

然後也不需要考慮相隔很遠的兩個數,可以考慮相鄰兩個數,結論也是一樣的,因為交換相鄰兩個數也可以使得序列排序。

程式碼

教你 \(17\)\(python3\) 程式碼水過2333

n = (int)(input())
a, b = map(int, input().split())
array = [[0] * 2] * n
for i in range(0, n):
    array[i] = list(map(int, input().split()))

def Cmp(elem):
    return elem[0] * elem[1]
array.sort(key = Cmp)

ans = 0
tot = a
for i in range(0, n):
    ans = max(ans, tot // array[i][1])
    tot = tot * array[i][0]

print(ans)