Everything Is Generated In Equal Probability (HDU-6595, probability expectation)

1. Title link:

HDU-6595

2. The main idea of ​​the topic:

The title is given a positive integer N.

Randomly select a positive integer n with equal probability in the interval [1, N], then randomly generate a permutation A of length n with equal probability, and then call the function CALCULATE(A).

SUBSEQUENCE(A): randomly generate a subsequence of sequence A.

CNTINVERSIONPAIRS(A): Returns the reverse logarithm of sequence A.

CALCULATE(A): Calculate the inverse number C of sequence A, then randomly select a subsequence B of A, and recursively return C + CALCULATE(B).

What is the expectation of returning the result CALCULATE(A).

3. Analysis:

It is not difficult to find by finding the law or recursion or rigorous mathematical proof: the expectation of the reverse logarithm of a random arrangement of length n is  \frac{n \times (n - 1))}{4}.

The probability of selecting a subsequence of length m in an arrangement of length n is \frac{C_n^m}{2^n}.

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

Simplification can be obtained: 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}}.

From this, f[i] can be calculated recursively.

Then the final answer is \frac{\sum_{i=1}^{N}f[i]}{N}

4. Code implementation:

#include <bits/stdc++.h>
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;
}

 

Guess you like

Origin blog.csdn.net/The___Flash/article/details/107217183