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 .
The probability of selecting a subsequence of length m in an arrangement of length n is .
So ...
Simplification can be obtained: .
From this, f[i] can be calculated recursively.
Then the final answer is
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;
}