不失一般性的,我们设 x ≤ y x \le y x≤y。
从最简单的情况考虑,当 x = y x = y x=y 时, f ( x , y ) = 0 + 0 = 0 f(x,y) = 0 + 0 = 0 f(x,y)=0+0=0。以下均为 x < y x < y x<y 的情况,推推式子可知:
f ( x , y ) = x m o d y + y m o d x = x + y − ⌊ x y ⌋ y − ⌊ y x ⌋ x f(x,y) = x \bmod y + y \bmod x= x + y - \lfloor\frac{x}{y}\rfloor y - \lfloor\frac{y}{x}\rfloor x f(x,y)=xmody+ymodx=x+y−⌊yx⌋y−⌊xy⌋x
由于 x < y x < y x<y,式子可以进一步化简:
f ( x , y ) = x + y − ⌊ y x ⌋ x f(x,y) = x + y - \lfloor\frac{y}{x}\rfloor x f(x,y)=x+y−⌊xy⌋x
由 x < y x < y x<y 可知 ⌊ y x ⌋ ≥ 1 \lfloor\frac{y}{x}\rfloor \ge 1 ⌊xy⌋≥1,于是可以得到以下观察:
x ≤ x + y m o d x = f ( x , y ) = y − ( ⌊ y x ⌋ − 1 ) x ≤ y x \le x + y \bmod x = f(x,y) = y - (\lfloor\frac{y}{x}\rfloor - 1)x \le y x≤x+ymodx=f(x,y)=y−(⌊xy⌋−1)x≤y
分析可知,当 x ∣ y x \mid y x∣y 时不等式左侧取等;当 x < y < 2 x x < y < 2x x<y<2x 时不等式右侧取等。
接下来考虑对于任意前缀长度为 k k k 的答案是怎么取到的。当 n = 1 n = 1 n=1 时答案显然为 0 0 0, n = 2 n = 2 n=2 时为 a 1 m o d a 2 + a 2 m o d a 1 a_1 \bmod a_2 + a_2 \bmod a_1 a1moda2+a2moda1。对于 n ≥ 3 n \ge 3 n≥3 的情况,考虑 f ( x , y ) f(x,y) f(x,y) 与 f ( y , z ) f(y,z) f(y,z) 满足 x ≤ y ≤ z x \le y \le z x≤y≤z,由不等式可知 x ≤ f ( x , y ) ≤ y ≤ f ( y , z ) ≤ z x \le f(x,y) \le y \le f(y,z) \le z x≤f(x,y)≤y≤f(y,z)≤z,因此可以证明前缀长度为 k k k 的最大值里一定有一个数取到 max i = 1 k { a i } \max \limits_{i = 1}^k\{a_i\} i=1maxk{ai}。
再由不等式可知存在 y ≥ 2 x y \ge 2x y≥2x 的情况时才会使得答案变得不确定,而这种情况最多只会有 log \log log 次,因此直接暴力更新即可,总时间复杂度 O ( n log n ) O(n \log n) O(nlogn)。
代码如下:
void solve ()
{
int n = read ();
vector <int> a (n + 1),ans (n + 1,0);
for (int i = 1;i <= n;++i) a[i] = read ();
int mx = a[1];
for (int i = 2;i <= n;++i)
{
if (a[i] > mx)
{
if (a[i] >= mx * 2) {for (int j = 1;j < i;++j) ans[i] = max (ans[i],a[i] % a[j] + a[j] % a[i]);}
else ans[i] = a[i];
mx = a[i];
}
else ans[i] = max (ans[i - 1],mx % a[i] + a[i] % mx);
}
for (int i = 1;i <= n;++i) printf ("%d ",ans[i]);
puts ("");
}
1178

被折叠的 条评论
为什么被折叠?



