atcoder-solutionsatcoder-solutions
abc468_e

Sum of Average の解説

abc468_e by @ohnuma

解説

Akに対する寄与を考える。

∑k=1NAk×∑l=1k∑r=kN1r−l+1\sum_{k=1}^{N} A_k \times \sum_{l=1}^{k} \sum_{r=k}^{N} \frac{1}{r - l + 1}

Akを固定した時にここを高速に求めることを考える

∑l=1k∑r=kN1r−l+1\sum_{l=1}^{k} \sum_{r=k}^{N} \frac{1}{r - l + 1}

ここで、以下のように定義すると

Hi=∑k=1i1kH_i = \sum_{k=1}^{i} \frac{1}{k} ∑l=1k(HN−l+1−Hk−l)\sum_{l=1}^{k} (H_{N - l + 1} - H_{k - l})

とできる。

∑l=1kHN−l+1\sum_{l=1}^{k} H_{N - l + 1}

についてはj = l - 1とすることで

∑j=0k−1HN−j\sum_{j=0}^{k - 1} H_{N - j}

とでき、

∑l=1kHk−l\sum_{l=1}^{k} H_{k - l}

については j = k - lとすることで

∑j=0k−1Hj\sum_{j=0}^{k - 1} H_{j}

とできるので、

もとの式は

∑k=1NAk×∑j=0k−1(HN−j−Hj)\sum_{k=1}^{N} A_k \times \sum_{j=0}^{k - 1} (H_{N - j} - H_{j})

とできる。

右側はkをなめると同時に計算することができるのでO(N)で解ける。

fn main() { input! { n: usize, a: [ModInt998244353; n] } let h = { let mut v = vec![]; v.push(ModInt998244353::new(0)); for num in 1..=n { v.push(ModInt998244353::new(1) / num); } PrefixSum1D::new(&v) }; let mut ans = ModInt998244353::new(0); let mut acc = ModInt998244353::new(0); for k in 0..n { acc += h.prefix_sum(n - k + 1) - h.prefix_sum(k + 1); ans += a[k] * acc; } println!("{}", ans); }

コメント