題目
F - Maximum Composition
給定 \(n\) 個函式 \(f_i\),其中 \(f_i(x) = a_i x + b_i\)。
對於所有元素互不相同的序列 \(p = (p_1, p_2, \cdots, p_k)\),其中所有元素均在 \([1, n]\) 中,求 \(f_{p_1}(f_{p_2}(\cdots(f_{p_k}(1))))\) 的最大值。
\(1 \leq n \leq 2 \times 10^5\),\(1 \leq k \leq \min\{ n, 10 \}\),\(1 \leq a_i, b_i \leq 50\)。
題解
首先有一個很顯然的性質,就是這個複合函式是單調遞增的。因此若 \(p\) 的前面確定,則只需最大化後面的函式值。
考慮對於給定的一組 \(p_k\),將它們如何排列才能使得答案最大。
假設我們已經找到了一組最優解 \(p\)。
考慮對於 \(p\) 中相鄰的兩項 \(i\) 和 \(j\),其中 \(i\) 在 \(j\) 前面,交換它們的順序對函式值的大小有什麼影響。由上面的分析,對整體函式值的影響等價於對以 \(i\) 開頭的字尾的函式值的影響。而又由假設,\(j\) 之後的函式值是確定的,因此只需比較以下兩個函式的大小:
把它們的表示式寫出來,得
由最優解的假設,必有 \(f_i(f_j(x)) \geq f_j(f_i(x))\)。這等價於
移項,得
移項,得
因此,對變數 \(i\),最優解 \(p\) 一定滿足 \(\dfrac{a_i - 1}{b_i}\) 的值單調不增。
因此,只需將給定的陣列 \(\{(a_i, b_i)\}\) 按 \(\dfrac{a_i - 1}{b_i}\) 從大到小排序,然後 01 揹包即可。
時間複雜度為 \(\Theta(nk)\)。
程式碼
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N=200003,M=13;
const long long NIN=-1e17;
int n,m,a[N],b[N],c[N];
long long f[N][M];
bool cmp(const int& u,const int& v){
return (a[u]-1)*b[v]<(a[v]-1)*b[u];
}
int main(){
// freopen("composition.in","r",stdin);
// freopen("composition.out","w",stdout);
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
for(i=1;i<=n;i++) c[i]=i;
sort(c+1,c+n+1,cmp);
memset(f,NIN,sizeof f);
f[0][0]=1;
for(i=1;i<=n;i++)
for(j=1,f[i][0]=1;j<=m;j++)
f[i][j]=max(f[i-1][j],f[i-1][j-1]*a[c[i]]+b[c[i]]);
printf("%lld",f[n][m]);
// fclose(stdin);
// fclose(stdout);
return 0;
}