ABC366F

dengrongkuo發表於2024-08-11

題目

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)), f_j(f_i(x)) \]

把它們的表示式寫出來,得

\[f_i(f_j(x)) = a_i(a_j x + b_j) + b_i = a_i a_j x + a_i b_j + b_i \]

\[f_j(f_i(x)) = a_j(a_i x + b_i) + b_j = a_i a_j x + a_j b_i + b_j \]

由最優解的假設,必有 \(f_i(f_j(x)) \geq f_j(f_i(x))\)。這等價於

\[a_i b_j + b_i \geq a_j b_i + b_j \]

移項,得

\[(a_i - 1)b_j \geq (a_j - 1)b_i \]

移項,得

\[\dfrac{a_i - 1}{b_i} \geq \dfrac{a_j - 1}{b_j} \]

因此,對變數 \(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;
}