[AGC028B]Removing Blocks(概率与期望)

mac2022-06-30  23

Solution:

​ 直接计算不是很好搞,于是考虑将代价和变成代价的平均值乘以方案数( \(n!\) )

​ 即 \(Ans = \text{删除物品的期望代价}\times n!\)

​ 由期望的线性性质,考虑每一个 \(a_i\) 对期望代价的贡献,对于 \(a_i\)\(a_j\), 若 \(i\)\(j\) 有贡献,必然是第一个删除 \(j\) ,这样 \(a_i\) 的值会被 \(j\) 统计一次,这样的概率为 \(\frac{1}{|j-i|+1}\),于是有:\[ Contribution(a_i) = a_i\sum_{j=1}^n\frac{1}{|j-i|+1} \] 答案为\[ \sum_{i=1}^na_i\sum_{j=1}^n\frac{1}{|j-i|+1} \] 前缀和优化逆元。

Code

#include <vector> #include <cmath> #include <cstdio> #include <cassert> #include <cstring> #include <iostream> #include <algorithm> typedef long long LL; typedef unsigned long long uLL; #define fir first #define sec second #define SZ(x) (int)x.size() #define MP(x, y) std::make_pair(x, y) #define PB(x) push_back(x) #define debug(...) fprintf(stderr, __VA_ARGS__) #define GO debug("GO\n") #define rep(i, a, b) for (register int i = (a), i##end = (b); (i) <= i##end; ++ (i)) #define drep(i, a, b) for (register int i = (a), i##end = (b); (i) >= i##end; -- (i)) #define REP(i, a, b) for (register int i = (a), i##end = (b); (i) < i##end; ++ (i)) inline int read() { register int x = 0; register int f = 1; register char c; while (!isdigit(c = getchar())) if (c == '-') f = -1; while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar())); return x * f; } template<class T> inline void write(T x) { static char stk[30]; static int top = 0; if (x < 0) { x = -x, putchar('-'); } while (stk[++top] = x % 10 xor 48, x /= 10, x); while (putchar(stk[top--]), top); } template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; } #define int LL using namespace std; const int maxn = 1e5 + 2; const int MOD = 1e9 + 7; LL a[maxn], n; LL inv[maxn], sum[maxn]; void Input() { n = read(); rep (i, 1, n) a[i] = read(); } void Init() { inv[0] = 0; inv[1] = 1; sum[1] = inv[1]; rep (i, 2, n) { inv[i] = (MOD - (MOD / i) * inv[MOD % i] % MOD) % MOD; sum[i] = (sum[i - 1] + inv[i]) % MOD; } } int factor(int n) { int ans = 1; rep (i, 2, n) ans = ans * i % MOD; return ans; } void Solve() { LL ans(0); rep (i, 1, n) { ans = (ans + a[i] * ((sum[i] - sum[0] + sum[n - i + 1] - sum[1] + MOD) % MOD) % MOD ) % MOD; } cout << ans * factor(n) % MOD << endl; } signed main() { Input(); Init(); Solve(); return 0; }

转载于:https://www.cnblogs.com/cnyali-Tea/p/11439872.html

最新回复(0)