P8590 『JROI-8』这是新历的朝阳,也是旧历的残阳 题解
ScottSuperb · · 题解
解法分析
贪心。我们分正负数两种情况分析:
对于正数。因为可以有空段,那么把所有正数都放最后一段就行了。利用初中简单整式乘法知识推一下每轮结果是如何增加的:首先由完全平方公式
代码实现中用变量
对于负数。首先想让平方和大就是要让绝对值大,那么在某个负数加上段数(就是把它放在最后一段会给它加上的数)后的绝对值大于它加
代码
先算出第一轮(
读写函数定义已省略。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
ll a[1000005];
int main() {
int n = read(), k = read(), b = 0;
ll q = 0, ans = 0, psum = 0, del;
for (int i = 0; i < n; ++i)
a[i] = read(), b += a[i] < 0, q = (q + (a[i] + 1) * (a[i] + 1) % mod) % mod;
ans += q;
for (int i = b; i < n; ++i) psum = (psum + a[i] + 1 % mod) % mod;
n = n - b;
for (int m = 2; m <= k; ++m) {
ans = (ans + (q = (q + psum * 2 % mod + n) % mod)) % mod,
psum = (psum + n) % mod;
while (b > 0 && a[b - 1] + m > abs(a[b - 1] + 1)) {
--b, ++n;
del = (a[b] + m) * (a[b] + m) % mod - (a[b] + 1) * (a[b] + 1) % mod;
ans = (ans + del) % mod, q = (q + del) % mod, psum = (psum + (a[b] + m) % mod) % mod;
}
}
write(ans);
fls();
return 0;
}