2020 ICPC Macau A. Accelerator(期望,计数,分治FFT)(每日一题 21.7.6)
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020 ICPC Macau A. Accelerator(期望,计数,分治FFT)(每日一题 21.7.6)相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
2020 ICPC Macau A. Accelerator(分治FFT)
Problem
给定长度为 n n n 的数组 a i a_i ai ,对于 1 ∼ n 1\\sim n 1∼n 的所有的排列 p i p_i pi ,计算 ( ( ( ( 0 + 1 ) ∗ a p 1 + 1 ) ∗ a p 2 + ⋯ ) + 1 ) ∗ a p n ((((0 + 1) *a_{p_1} + 1) * a_{p_2} + \\cdots) + 1) * a_{p_n} ((((0+1)∗ap1+1)∗ap2+⋯)+1)∗apn 的期望。
n ≤ 1 0 5 n\\le 10^5 n≤105
Solution
显然我们把要求的式子展开以后有:
v a l = ∏ i = 1 n a p i + ∏ i = 2 n a p i + ⋯ + ∏ i = n n a p i val = \\prod\\limits_{i = 1}^{n}a_{p_i} + \\prod\\limits_{i = 2}^{n}a_{p_i} + \\cdots + \\prod\\limits_{i = n}^{n}a_{p_i} val=i=1∏napi+i=2∏napi+⋯+i=n∏napi
考虑对于任意一个排列的乘积, ∏ i n a p i \\displaystyle\\prod\\limits_{i}^{n}a_{p_i} i∏napi ,它自己对于答案期望的贡献。
显然期望等于权值乘以概率,对于一段长度为 i i i 的排列,它的概率显然为 i ! × ( n − i ) ! n ! \\cfrac{i!\\times (n-i)!}{n!} n!i!×(n−i)!,那么它对答案的贡献显然为 ∏ i n a p i × i ! × ( n − i ) ! n ! \\displaystyle\\prod\\limits_{i}^{n}a_{p_i}\\times \\cfrac{i!\\times (n-i)!}{n!} i∏napi×n!i!×(n−i)!
由于期望的可加性,我们发现对于所有的长度为 i i i 的排列,它的贡献均为 ∏ i n a p i × i ! × ( n − i ) ! n ! \\displaystyle\\prod\\limits_{i}^{n}a_{p_i}\\times \\cfrac{i!\\times (n-i)!}{n!} i∏napi×n!i!×(n−i)!,所以我们可以设 f i f_i fi 表示从 n n n 个数中取 i i i 个数的乘积和 f ( i ) = ∑ p ∈ S ∏ i n a p i f(i)=\\displaystyle\\sum_{p\\in S}\\prod\\limits_{i}^{n}a_{p_i} f(i)=p∈S∑i∏napi , S S S 为从 n n n 个数中取 i i i 个数的集合。
显然要求的答案期望 E ( x ) E(x) E(x) :
E ( x ) = ∑ i = 1 n f i × i ! × ( n − i ) ! n ! \\begin{aligned} E(x)= \\cfrac{\\sum\\limits_{i = 1} ^ {n} f_i\\times i! \\times (n - i) !}{n!} \\end{aligned} E(x)=n!i=1∑nfi×i!×(n−i)!
也就是我们只需要求出 1 ∼ n 1\\sim n 1∼n 的 f i f_i fi 即可。
显然有:
f i = ∑ j = 1 i f i − j × f j f_i=\\sum_{j=1}^{i}f_{i-j}\\times f_j fi=j=1∑ifi−j×fj
f 1 = a i f_1=a_i f1=ai
发现这显然就是一个自己卷自己的分治FFT的模板,直接用分治FFT O ( n log 2 n ) O(n\\log^2 n) O(nlog2n) 计算即可。
Hint
CF GNU C++17 (64) = 327 ms,GNU C++17 = 951 ms ∼ \\sim ∼ TLE …
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 5, mod = 998244353, P = 998244353, MOD = 998244353;
template <typename T> inline void read(T& t) {
int f = 0, c = getchar(); t = 0;
while (!isdigit(c)) f |= c == '-', c = getchar();
while (isdigit(c)) t = t * 10以上是关于2020 ICPC Macau A. Accelerator(期望,计数,分治FFT)(每日一题 21.7.6)的主要内容,如果未能解决你的问题,请参考以下文章
The 2020 ICPC Asia Macau Regional Contest B Boring Problem
ACM-ICPC 2017 Asia Urumqi A. Coins
2018 ICPC Asia Singapore Regional A. Largest Triangle (计算几何)
ACM-ICPC 2018 徐州赛区网络预赛 A. Hard to prepare