题目
题意:给定两个长度为n的数组
a
,
b
a,b
a,b,可以交换对应位置的
a
i
,
b
i
,
1
<
=
i
<
=
n
a_i,b_i,1<=i<=n
ai,bi,1<=i<=n。问能得到的、最小的
∑
i
=
1
n
∑
j
=
i
+
1
n
(
a
i
+
a
j
)
2
\sum_{i=1}^{n}\sum_{j=i+1}^{n}(a_i+a_j)^2
∑i=1n∑j=i+1n(ai+aj)2+
∑
i
=
1
n
∑
j
=
i
+
1
n
(
b
i
+
b
j
)
2
\sum_{i=1}^{n}\sum_{j=i+1}^{n}(b_i+b_j)^2
∑i=1n∑j=i+1n(bi+bj)2是多少。
思路:令 s = ∑ i = 1 n a i s=\sum_{i=1}^na_i s=∑i=1nai,则 ∑ i = 1 n ∑ j = i + 1 n ( a i + a j ) 2 = ( n − 1 ) ∗ ∑ i = 1 n a i 2 + ∑ i = 1 n a i ∗ ( s − a i ) = ( n − 2 ) ∗ ∑ i = 1 n a i 2 + ∑ i = 1 n a i 2 \sum_{i=1}^{n}\sum_{j=i+1}^{n}(a_i+a_j)^2=(n-1)*\sum_{i=1}^n{a_i}^2+\sum_{i=1}^{n} a_i*(s-a_i)=(n-2)*\sum_{i=1}^n{a_i}^2+\sum_{i=1}^n{a_i}^2 ∑i=1n∑j=i+1n(ai+aj)2=(n−1)∗∑i=1nai2+∑i=1nai∗(s−ai)=(n−2)∗∑i=1nai2+∑i=1nai2
所以 ∑ i = 1 n ∑ j = i + 1 n ( a i + a j ) 2 \sum_{i=1}^{n}\sum_{j=i+1}^{n}(a_i+a_j)^2 ∑i=1n∑j=i+1n(ai+aj)2+ ∑ i = 1 n ∑ j = i + 1 n ( b i + b j ) 2 = ( n − 2 ) ∗ ∑ i = 1 n ( a i 2 + b i 2 ) + ( ∑ i = 1 n a i ) 2 + ( ∑ i = 1 n b i ) 2 \sum_{i=1}^{n}\sum_{j=i+1}^{n}(b_i+b_j)^2=(n-2)*\sum_{i=1}^n({a_i}^2+{b_i}^2)+(\sum_{i=1}^n{a_i})^2+(\sum_{i=1}^n{b_i})^2 ∑i=1n∑j=i+1n(bi+bj)2=(n−2)∗∑i=1n(ai2+bi2)+(∑i=1nai)2+(∑i=1nbi)2
由于 ( n − 2 ) ∗ ∑ i = 1 n ( a i 2 + b i 2 ) (n-2)*\sum_{i=1}^n({a_i}^2+{b_i}^2) (n−2)∗∑i=1n(ai2+bi2)是固定的,原题等价于最小化 ( ∑ i = 1 n a i ) 2 + ( ∑ i = 1 n b i ) 2 (\sum_{i=1}^n{a_i})^2+(\sum_{i=1}^n{b_i})^2 (∑i=1nai)2+(∑i=1nbi)2
令 s u m a = ∑ i = 1 n a i , s u m b = ∑ i = 1 n b i suma=\sum_{i=1}^n{a_i},sumb=\sum_{i=1}^n{b_i} suma=∑i=1nai,sumb=∑i=1nbi,因为 s u m = s u m a + s u m b sum=suma+sumb sum=suma+sumb是固定的,要使 s u m a 2 + s u m b 2 suma^2+sumb^2 suma2+sumb2尽可能小,要让 s u m a , s u m b suma,sumb suma,sumb尽可能平均(周长相同的情况下,正方形是面积最小的四边形。代数上也很好证明)。
令
c
i
=
m
a
x
(
a
i
,
b
i
)
−
m
i
n
(
a
i
,
b
i
)
c_i=max(a_i,b_i)-min(a_i,b_i)
ci=max(ai,bi)−min(ai,bi),
s
=
∑
c
i
∗
(
1
取
/
0
不
取
)
s=\sum c_i*(1取/0不取)
s=∑ci∗(1取/0不取),则
s
u
m
a
=
s
+
∑
i
=
1
n
m
i
n
(
a
i
,
b
i
)
,
s
u
m
b
=
s
u
m
−
s
u
m
a
suma=s+\sum_{i=1}^nmin(a_i,b_i),sumb=sum-suma
suma=s+∑i=1nmin(ai,bi),sumb=sum−suma。
要使suma,sumb接近,s要尽量接近总量
∑
c
i
\sum c_i
∑ci的一半,则相当于从背包
m
=
(
∑
c
i
)
/
2
m=(\sum c_i )/2
m=(∑ci)/2中尽可能装满物品。01背包模型。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 200010;
int t;
int a[maxn], b[maxn], n;
int dp[maxn];
void solve() {
scanf("%d", &n);
int sum = 0, res = 0;
int all = 0, ans = 0;
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
all += a[i];
ans += a[i] * a[i];
}
for (int i = 0; i < n; ++i) {
scanf("%d", &b[i]);
all += b[i];
ans += b[i] * b[i];
if (a[i] > b[i]) {
swap(a[i], b[i]);
}
res += a[i];
b[i] -= a[i];
sum += b[i];
}
// 01背包
memset(dp, 0, sizeof(dp));
int m = sum / 2;
for (int i = 0; i < n; ++i) {
for (int j = m; j >= b[i]; --j) {
dp[j] = max(dp[j], dp[j-b[i]] + b[i]);
}
}
int suma = res + dp[m];
int sumb = all - suma;
ans = ans * (n - 2) + suma * suma + sumb * sumb;
printf("%d\n", ans);
}
int main() {
scanf("%d", &t);
while (t--) {
solve();
}
}
另一种思路:定义
d
p
i
w
dp_{iw}
dpiw,表示取前i个数,是否能可达
w
w
w这个分,可达则为
t
r
u
e
true
true,否则为
f
a
l
s
e
false
false。
d
p
[
i
]
[
w
]
=
m
a
x
(
d
p
[
i
−
1
]
[
w
−
a
[
i
]
]
,
d
p
[
i
−
1
]
[
w
−
b
[
i
]
]
)
dp[i][w]=max(dp[i-1][w-a[i]],dp[i-1][w-b[i]])
dp[i][w]=max(dp[i−1][w−a[i]],dp[i−1][w−b[i]])
最后,从
d
p
n
w
=
t
r
u
e
dp_nw=true
dpnw=true的所有
w
w
w中,suma的值,取
∣
s
u
m
a
−
s
u
m
b
∣
|suma-sumb|
∣suma−sumb∣最小的那个。计算对应的答案值。