zoukankan      html  css  js  c++  java
  • [生成函数] Codeforces 891E Lust

    题目大意

    给你一个长为 (n) 的序列 ({a_n}),和一个初值为0的变量 (s),要求你重复以下操作 (k) 次:

    • (1,2,cdots,n) 中等概率随机选择一个 (x)
    • (s) 加上 (prod_{i eq x}a_i)
    • (a_i) 减一

    (k) 次操作后 (s) 的期望。

    (1leq nleq 5000,1leq kleq 10^9,0leq a_ileq 10^9)

    题解

    假设当前令 (a_x) 减一,那么

    [ s+=prod_{i eq x}a_i=(a_x-(a_x-1))prod_{i eq x}a_i\ =prod_ia_i-(a_x-1)prod_{i eq x} a_i ]

    发现 (s) 加上的是数列操作前后整个数列乘积的差值。显然操作多次的贡献就是还没有操作时数列的乘积减去操作结束后数列的乘积。设 (a_i) 被操作了 (b_i) 次,变成了 (a_i-b_i),则有

    [s=prod_{i=1}^na_i-prod_{i=1}^n(a_i-b_i) ]

    因此我们只需要求得 (prod_{i=1}^n(a_i-b_i)) 的期望。

    ({a_n}) 操作 (k) 次有 (n^k) 次种方案,对于每一种 ({b_n}),又有 (frac{k!}{b_1!b_2!cdots b_n!}) 种操作方案,所以有

    [Eleft(prod_{i=1}^n(a_i-b_i) ight)=frac{1}{n^k}sum_{{b_n}}frac{k!}{prod_{i=1}^nb_i!}prod_{i=1}^n(a_i-b_i)\ =frac{k!}{n^k}sum_{{b_n}}prod_{i=1}^nfrac{a_i-b_i}{b_i!} ]

    (a_i) 被操作 (j) 次的贡献是 (frac{a_i-j}{j!}),设这个生成函数为

    [f_i(x)=sum_{j=0}^inftyfrac{a_i-j}{j!} x^j ]

    [sum_{{b_n}}prod_{i=1}^nfrac{a_i-b_i}{b_i!}=[x^k]prod_{i=1}^n f_i(x)=[x^k]prod_{i=1}^nsum_{j=0}^inftyfrac{a_i-j}{j!}x^j\ =[x^k]prod_{i=1}^nleft(a_isum_{j=0}^inftyfrac{x^j}{j!}-xsum_{j=1}^inftyfrac{x^{j-1}}{(j-1)!} ight)\ =[x^k]prod_{i=1}^nleft(a_isum_{j=0}^inftyfrac{x^j}{j!}-xsum_{j=0}^inftyfrac{x^j}{j!} ight)\ =[x^k]prod_{i=1}^n(a_i-x)e^x\ =[x^k]e^{nx}prod_{i=1}^n(a_i-x) ]

    因为 (nleq 5000),所以对于 (prod_{i=1}^n(a_i-x)),可以 (O(n^2)) 暴力求出。设 (g(x)=prod_{i=1}^n(a_i-x)),则我们要求 ([x^k]e^{nx}g(x))。不妨再把 (e^{nx}) 展开,有

    [[x^k](e^{nx}g(x))=[x^k]left(g(x)sum_{i=0}^inftyfrac{n^i}{i!}x^i ight)\ =sum_{i=0}^nleft([x^i]g(x) imesfrac{n^{k-i}}{(k-i)!} ight) ]

    回代得

    [Eleft(prod_{i=1}^n(a_i-b_i) ight)=frac{k!}{n^k}sum_{i=0}^nleft([x^i]g(x) imesfrac{n^{k-i}}{(k-i)!} ight)\ =sum_{i=0}^nleft([x^i]g(x) imesfrac{k^{underline{i}}}{n^i} ight) ]

    该式可以 (O(n)) 求出。最后,

    [E(s)=prod_{i=1}^na_i-sum_{i=0}^nleft([x^i]g(x) imesfrac{k^{underline{i}}}{n^i} ight) ]

    因此本题的时间复杂度为 (O(n^2))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    const LL MOD = 1000000007LL;
    LL a[5005], g[5005];
    int n, k;
    
    LL qpow(LL b, LL n) {
        LL x = 1, Power = b % MOD;
        while (n) {
            if (n & 1) x = x * Power % MOD;
            Power = Power * Power % MOD;
            n >>= 1;
        }
        return x;
    }
    
    LL calc() {
        g[0] = 1;
        for (int i = 1;i <= n;++i) {
            for (int j = n;j >= 1;--j)
                g[j] = ((g[j] * a[i] % MOD - g[j - 1]) % MOD + MOD) % MOD;
            g[0] = g[0] * a[i] % MOD;
        }
        LL ninv = qpow(n, MOD - 2), temp = 1, ans = 0;
        for (int i = 0;i <= n;++i) {
            ans = (ans + g[i] * temp % MOD) % MOD;
            temp = temp * ninv % MOD * (k - i) % MOD;
        }
        temp = 1;
        for (int i = 1;i <= n;++i) temp = temp * a[i] % MOD;
        ans = ((temp - ans) % MOD + MOD) % MOD;
        return ans;
    }
    
    int main() {
        scanf("%d%d", &n, &k);
        for (int i = 1;i <= n;++i)
            scanf("%I64d", &a[i]);
        printf("%I64d
    ", calc());
    
        return 0;
    }
    
  • 相关阅读:
    php数据缓存到文件类设计
    php静态文件缓存示例
    php array_merge和“+”的区别和使用《细说php2》
    kafka环境安装及简单使用(单机版)
    Protobuf的上手使用
    Java8新特性概览
    Mock测试框架(Mockito为例)
    Java序列化与反序列化
    系统/项目环境搭建
    关于Tomcat服务器中的协议及请求过程
  • 原文地址:https://www.cnblogs.com/AEMShana/p/15143461.html
Copyright © 2011-2022 走看看