ABC399F - Range Power Sum

問題
リンク 長さの整数列とが与えられるので、以下の式ををmod 998で求めて下さい。
解法
とりあえず与えられた式を理解しやすいように書き換えると、
という3重シグマの形になる。が、一番内側のシグマについては区間和を表しているので、累積和を用いることで容易に外せる。数列を, とすると、
となる。どう考えても乗の部分が厄介なので、二項展開1を用いてこれを外すと、以下のようになる。
3重シグマとなったが、これらを交換しても答えは変わらない。また、シグマから外側に出せるものは出してしまうことにする。これらを適用すると、式は以下のように変形できる。
ここで、はの累積和を前計算しておくことによって、各に対してで計算ができる。よって全体でで解くことが可能で、この問題の制約下では十分高速になる。
提出
using mint = modint998244353;
mint ncr(int n, int r) {
mint res = 1;
rep(i,r) {
res *= (n-i);
}
rep(i,r) {
res /= (i+1);
}
return res;
}
void solve() {
int n, k; cin >> n >> k;
auto a = i64_vec_IN(n);
vector<mint> csum(n+1, 0);
rep(i,n) csum[i+1] = csum[i] + a[i];
vector<vector<mint>> ccsum(k+1, vector<mint>(n+2, 0));
rep(p, k+1) {
rep(i, n+1) {
ccsum[p][i+1] = ccsum[p][i] + csum[i].pow(p);
}
}
mint ans = 0;
rep(p,k+1){
mint s = 0;
rep(l,n) {
s += (csum[l] * (-1)).pow(p) * (ccsum[k-p][n+1] - ccsum[k-p][l+1]);
}
ans += s * ncr(k,p);
}
cout << ans.val() << '
';
}