Everything Is Generated In Equal Probability(HDU - 6595,概率期望)

一.题目链接:

HDU-6595

二.题目大意:

题目给定一个正整数N.

在区间[1, N]中随机等概率地选取一个正整数n,然后随机等概率地生成一个长度为n的排列A,然后调用函数 CALCULATE(A).

Everything Is Generated In Equal Probability(HDU - 6595,概率期望)_第1张图片

SUBSEQUENCE(A):随机生成一个序列A的子序列.

CNTINVERSIONPAIRS(A):返回序列A的逆序对数.

CALCULATE(A):计算序列A的逆序数C,再随机选取一个A的子序列B,递归返回C + CALCULATE(B).

求返回结果CALCULATE(A)的期望.

三.分析:

通过找规律或递推或严格的数学证明都不难得到:长度为 n 的随机排列的逆序对数的期望为 \frac{n \times (n - 1))}{4}.

在长度为n的排列中选取了长度为m的子序列的概率为\frac{C_n^m}{2^n}.

所以 f[n] = \frac{n \times (n - 1)}{4} + \sum_{i = 0}^n \frac{C_n^i}{2^n} f[i].

化简可得:f[n] = \frac{\frac{n \times (n - 1)}{4} + \sum_{i = 0}^{n - 1} \frac{C_n^i}{2^n} f[i]}{1-\frac{1}{2^n}}.

由此可递推计算f[i].

那么最终答案为 \frac{\sum_{i=1}^{N}f[i]}{N}

四.代码实现:

#include 
using namespace std;

typedef long long ll;

const int M = (int)3e3;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;
const double eps = 1e-5;

ll f[M + 5];
ll fac[M + 5];
ll invfac[M + 5];
ll c[M + 5][M + 5];
ll g[M + 5];

ll quick(ll a, ll b, ll p)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return s;
}

ll inv(ll n, ll p)
{
    return quick(n, p - 2, p);
}

ll C(ll n, ll m, ll p)
{
    return fac[n] * invfac[m] % mod * invfac[n - m] % mod;
}

void init()
{
    fac[0] = 1; for(int i = 1; i <= M; ++i) fac[i] = fac[i - 1] * i % mod, invfac[i] = inv(fac[i], mod);
    for(int i = 0; i <= M; ++i) for(int j = 0; j <= i; ++j) c[i][j] = C(i, j, mod);
    ll p = 1, inv4 = inv(4, mod), sum = 0;
    for(int i = 1; i <= M; ++i)
    {
        f[i] = i * (i - 1) % mod * inv4 % mod;
        ll s = 0; for(int j = 0; j < i; ++j) s = (s + c[i][j] * f[j] % mod) % mod;
        p = p * 2 % mod; f[i] = (f[i] + s * inv(p, mod) % mod) % mod;
        f[i] = f[i] * p % mod * inv(p - 1, mod) % mod;
        sum = (sum + f[i]) % mod;
        g[i] = sum * inv(i, mod) % mod;
    }
}

int main()
{
//    freopen("output.txt", "w", stdout);
    init();
    int n;
    while(~scanf("%d", &n)) printf("%lld\n", g[n]);
    return 0;
}

 

你可能感兴趣的:(#,概率)