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


    1.png

    Solution:

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

    ​ 即 (Ans = ext{删除物品的期望代价} imes n!)

    ​ 由期望的线性性质,考虑每一个 (a_i) 对期望代价的贡献,对于 (a_i)(a_j), 若 (i)(j) 有贡献,必然是第一个删除 (j) ,这样 (a_i) 的值会被 (j) 统计一次,这样的概率为 (frac{1}{|j-i|+1}),于是有:

    [Contribution(a_i) = a_isum_{j=1}^nfrac{1}{|j-i|+1} ]

    答案为

    [sum_{i=1}^na_isum_{j=1}^nfrac{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
    ")
    #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;
    }
    
  • 相关阅读:
    你有认真了解过自己的“Java对象”吗? 渣男
    布隆过滤器,你也可以处理十几亿的大数据
    阻塞队列——手写生产者消费者模式、线程池原理面试题真正的答案
    Java集合面试题汇总篇
    Github 骚操作
    责任链模式——更灵活的if else
    时间复杂度到底怎么算
    创造DotNet Core轻量级框架【二】
    创造DotNet Core轻量级框架【一】
    小胖李的面试之旅(二)
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/11439872.html
Copyright © 2020-2023  润新知