题目描述
JAG Box 是一种目前在全世界流行的普通长方体盒子。共有 N N N 个 JAG Box。对于每个 i = 1 , 2 , ... , N i = 1, 2, \ldots, N i=1,2,...,N,第 i i i 个盒子有一个整数重量 A i A_i Ai。
你将通过重复选择一个剩余的盒子并将其插入当前堆叠的最底部来建造一个垂直堆叠。当一个重量为 w w w 的盒子被插入到总重量为 x x x 的现有堆叠底部时,该盒子承受的负载等于 ⌊ x w ⌋ \left\lfloor \frac{x}{w} \right\rfloor ⌊wx⌋。
确定所有盒子可能承受的最小总负载。
输入格式
输入格式如下:
N A 1 A 2 ... A N \begin{aligned} &N \\ &A_1 \ A_2 \ \ldots \ A_N \end{aligned} NA1 A2 ... AN
- 2 ≤ N ≤ 200 000 2 \leq N \leq 200\,000 2≤N≤200000
- 1 ≤ A i ≤ 10 9 1 \leq A_i \leq 10^9 1≤Ai≤109 ( 1 ≤ i ≤ N 1 \leq i \leq N 1≤i≤N)
- 所有输入值均为整数。
输出格式
在一行中输出答案。
输入输出样例 #1
输入 #1
5
3 1 4 1 5
输出 #1
3
题意
有 N N N 个 JAG Box。对于每个 i = 1 , 2 , ... , N i = 1, 2, \ldots, N i=1,2,...,N,第 i i i 个盒子有一个整数重量 A i A_i Ai。
通过重复选择一个剩余的盒子并将其插入当前堆叠的最底部来建造一个垂直堆叠。当一个重量为 w w w 的盒子被插入到总重量为 x x x 的现有堆叠底部时,该盒子承受的负载等于 ⌊ x w ⌋ \left\lfloor \frac{x}{w} \right\rfloor ⌊wx⌋。
求所有盒子可能承受的最小总负载。
思路
考虑贪心做法,只需按 A i A_i Ai 升序排序即可。
采用邻项交换法证明,设当前的堆叠总重量为 x x x,现有升序排序后两个数 A i , A i + 1 A_i,A_{i+1} Ai,Ai+1( A i ≤ A i + 1 A_i \le A_{i+1} Ai≤Ai+1)。
- 顺序放入:负载为 S 1 = ⌊ x A i ⌋ + ⌊ x + A i A i + 1 ⌋ S_1 = \left\lfloor \frac{x}{A_i} \right\rfloor + \left\lfloor \frac{x + A_i}{A_{i+1}} \right\rfloor S1=⌊Aix⌋+⌊Ai+1x+Ai⌋。
- 反序放入:负载为 S 2 = ⌊ x A i + 1 ⌋ + ⌊ x + A i + 1 A i ⌋ S_2 = \left\lfloor \frac{x}{A_{i+1}} \right\rfloor + \left\lfloor \frac{x + A_{i+1}}{A_i} \right\rfloor S2=⌊Ai+1x⌋+⌊Aix+Ai+1⌋。
关键引理
对于任意正整数 n , m , k n,m,k n,m,k:
⌊ x + k m ⌋ − ⌊ x m ⌋ ∈ { 0 , 1 } \left\lfloor \frac{x + k}{m} \right\rfloor - \left\lfloor \frac{x}{m} \right\rfloor \in \{0,1\} ⌊mx+k⌋−⌊mx⌋∈{0,1}
- 若 k ≥ m k \ge m k≥m,则差值一定为 1 1 1;
- 若 k < m k < m k<m,差值为 0 0 0 或 1 1 1。
接着提出公共项:
S 1 = ⌊ x A i ⌋ + ⌊ x A i + 1 ⌋ + ( ⌊ x + A i A i + 1 ⌋ − ⌊ x A i + 1 ⌋ ) S_1 = \left\lfloor \frac{x}{A_i} \right\rfloor + \left\lfloor \frac{x}{A_{i+1}} \right\rfloor + (\left\lfloor \frac{x+A_i}{A_{i + 1}} \right\rfloor - \left\lfloor \frac{x}{A_{i+1}} \right\rfloor) S1=⌊Aix⌋+⌊Ai+1x⌋+(⌊Ai+1x+Ai⌋−⌊Ai+1x⌋)
S 2 = ⌊ x A i ⌋ + ⌊ x A i + 1 ⌋ + ( ⌊ x + A i + 1 A i ⌋ − ⌊ x A i ⌋ ) S_2 = \left\lfloor \frac{x}{A_i} \right\rfloor + \left\lfloor \frac{x}{A_{i+1}} \right\rfloor + (\left\lfloor \frac{x+A_{i + 1}}{A_i} \right\rfloor - \left\lfloor \frac{x}{A_i} \right\rfloor) S2=⌊Aix⌋+⌊Ai+1x⌋+(⌊Aix+Ai+1⌋−⌊Aix⌋)
- 因为 A i + 1 ≥ A i A_{i+1} \ge A_i Ai+1≥Ai,所以 ⌊ x + A i + 1 A i ⌋ − ⌊ x A i ⌋ = 1 \left\lfloor \frac{x+A_{i + 1}}{A_i} \right\rfloor - \left\lfloor \frac{x}{A_i} \right\rfloor = 1 ⌊Aix+Ai+1⌋−⌊Aix⌋=1;
- 因为 A i ≤ A i + 1 A_i \le A_{i+1} Ai≤Ai+1,所以 ⌊ x + A i A i + 1 ⌋ − ⌊ x A i + 1 ⌋ ∈ { 0 , 1 } \left\lfloor \frac{x+A_i}{A_{i + 1}} \right\rfloor - \left\lfloor \frac{x}{A_{i+1}} \right\rfloor \in \{0,1\} ⌊Ai+1x+Ai⌋−⌊Ai+1x⌋∈{0,1}。
于是总有:
⌊ x + A i A i + 1 ⌋ − ⌊ x A i + 1 ⌋ ≤ ⌊ x + A i + 1 A i ⌋ − ⌊ x A i ⌋ ⇒ S 1 ≤ S 2 \left\lfloor \frac{x+A_i}{A_{i + 1}} \right\rfloor - \left\lfloor \frac{x}{A_{i+1}} \right\rfloor \le \left\lfloor \frac{x+A_{i + 1}}{A_i} \right\rfloor - \left\lfloor \frac{x}{A_i} \right\rfloor \Rightarrow S_1 \le S_2 ⌊Ai+1x+Ai⌋−⌊Ai+1x⌋≤⌊Aix+Ai+1⌋−⌊Aix⌋⇒S1≤S2
即按 A i A_i Ai 升序排序最优。
代码
cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[200001],ans,cnt;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);//升序排序
cnt=a[1];
for(int i=2;i<=n;i++)
ans+=cnt/a[i],cnt+=a[i];//求负载
cout<<ans;
return 0;
}