牛客小白月赛110(EF)
E
比较有意思的思维题
按下标可以分为若干个组,先对每组内升序排序,再按值排序,一定是最优的。目前还不太会证明,以后有机会再补充证明,具体细节见代码。
F
双指针 + 模运算式推导
首先特判掉 \(x=0\) 的情况,因为只有不含0的数组才符合要求,所以只需要将所有 \(a[i]=0\) 改为非0值即可。
若区间 \([l,r]\) 不满足约束条件,即:
\[\frac {mul_{r}}{mul_{l-1}} mod p = x
\]
考虑将式子变换成:
\[mul_{r} = (x + k*p)*mul_{l-1} (k \in Z)
\]
\[\frac {mul_{r}}{x + k*p} = mul_{l-1}
\]
\[mul_{r} * inv(x + k*p) = mul_{l-1}
\]
其中
\[inv(x + k*p) = qpow(x + k*p, p-2,p) = (x+k*p)^{p-2} mod p = x^{p-2} mod p = inv(x)\]
因此:
\[mul_{r} * inv(x) = mul_{l-1}
\]
\(x\) 是固定的,对于任意固定右端点 \(r\) 的区间,只需要看其前缀是否有满足上式的左端点即可。
当 \(x \not= 0\) 时,对于任意包含0的子区间均满足条件。因此对于不合法区间,只需要将某个元素修改为0即可。
用双指针 \(l,r\) 来遍历,每次看右端点为 \(r\) 的所有子区间 \([l,r]\)是否均满足要求(\(l\) 范围在 \(r\) 之前的第一个 \(a[i]=0\) 的后一个位置),若存在不满足要求的左端点,则贪心地将最右侧端点 \(a[r]\) 赋为0即可(容易证明这样一定最优,因为保证了前面的同时,后面的区间范围更小了),并将 \(l\) 的范围更新成 \(>=r+1\)。具体细节见代码。