Everything Is Generated In Equal Probability
Problem Description
One day, Y_UME got an integer N and an interesting program which is shown below:
Y_UME wants to play with this program. Firstly, he randomly generates an integer n∈[1,N] in equal probability. And then he randomly generates a permutation of length n in equal probability. Afterwards, he runs the interesting program(function calculate()) with this permutation as a parameter and then gets a returning value. Please output the expectation of this value modulo 998244353.
A permutation of length n is an array of length n consisting of integers only ∈[1,n] which are pairwise different.
An inversion pair in a permutation p is a pair of indices (i,j) such that i>j and pi<pj. For example, a permutation [4,1,3,2] contains 4 inversions: (2,1),(3,1),(4,1),(4,3).
In mathematics, a subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. Note that empty subsequence is also a subsequence of original sequence.
Refer to https://en.wikipedia.org/wiki/Subsequence for better understanding.
Input
There are multiple test cases.
Each case starts with a line containing one integer N(1≤N≤3000).
It is guaranteed that the sum of Ns in all test cases is no larger than 5×104.
Output
For each test case, output one line containing an integer denoting the answer.
Sample Input
1
2
3
Sample Output
0
332748118
554580197
Source
2019 Multi-University Training Contest 2
Solution
和队友分头推表达式,默契地推出同一个式子哈哈
1到n的全排列的逆序对总数:
n
u
m
O
f
I
n
v
(
n
)
=
n
⋅
n
u
m
O
f
I
n
v
(
n
−
1
)
+
(
n
−
1
)
!
⋅
C
n
2
=
n
!
⋅
C
n
2
2
numOfInv(n) = n \cdot numOfInv(n - 1) + (n - 1)! \cdot C_n^2 = \frac{{n! \cdot C_n^2}}{2}
numOfInv(n)=n⋅numOfInv(n−1)+(n−1)!⋅Cn2=2n!⋅Cn2
最终答案:
a
n
s
=
1
n
∑
i
=
1
n
1
i
!
⋅
4
3
⋅
n
u
m
O
f
I
n
v
(
i
)
=
1
n
∑
i
=
1
n
1
i
!
⋅
4
3
⋅
i
!
⋅
C
i
2
2
=
1
n
∑
i
=
1
n
2
C
i
2
3
ans = \frac{1}{n}\sum\limits_{i = 1}^n {\frac{1}{{i!}}} \cdot \frac{4}{3} \cdot numOfInv(i) = \frac{1}{n}\sum\limits_{i = 1}^n {\frac{1}{{i!}}} \cdot \frac{4}{3} \cdot \frac{{i! \cdot C_i^2}}{2} = \frac{1}{n}\sum\limits_{i = 1}^n {\frac{{2C_i^2}}{3}}
ans=n1i=1∑ni!1⋅34⋅numOfInv(i)=n1i=1∑ni!1⋅34⋅2i!⋅Ci2=n1i=1∑n32Ci2
AC Code:
/*
* Copyright (c) 2019 Ng Kimbing, HNU, All rights reserved. May not be used, modified, or copied without permission.
* @Author: Ng Kimbing, HNU.
* @LastModified:2019-07-24 T 21:11:51.349 +08:00
*/
package ACMProblems.Summer2019.HDU.hdu2;
import static ACMProblems.ACMIO.*;
public class Main {
// Code for IO has been omitted.
private static final int MOD = 998244353;
private static final int maxN = 3005;
private static final long twoThird = 2 * powMod(3, MOD - 2, MOD);
private static long[] sum = new long[maxN];
private static long combination(long n, long m, int mod) {
//make it as small as possible
if (m > n - m)
m = n - m;
if (m == 0)
return 1;
long fz = 1, fm = 1;
for (int i = 1; i <= m; i++) {
fz = (fz * (n - i + 1)) % mod;
fm = (fm * i) % mod;
}
// n!/m!(n-m)!
long fmInv = powMod(fm, mod - 2, mod);
return (fz * fmInv) % mod;
}
private static long powMod(long a, long n, long mod) {
long ret = 1;
long temp = a % mod;
while (n != 0) {
if ((n & 1) != 0)
ret = ret * temp % mod;
temp = temp * temp % mod;
n >>= 1;
}
return ret;
}
public static void main(String[] args) throws Exception {
for (int i = 2; i < maxN; ++i)
sum[i] = (sum[i - 1] + combination(i, 2, MOD)) % MOD;
while (true) {
try {
int n = nextInt();
out.println(sum[n] * powMod(n, MOD - 2, MOD) % MOD * twoThird % MOD);
out.flush();
} catch (Exception ignored) {
out.flush();
break;
}
}
}
}
未化简的方法代码:
/*
* Copyright (c) 2019 Ng Kimbing, HNU, All rights reserved. May not be used, modified, or copied without permission.
* @Author: Ng Kimbing, HNU.
* @LastModified:2019-07-24 T 21:11:51.349 +08:00
*/
package ACMProblems.Summer2019.HDU.hdu2;
import static ACMProblems.ACMIO.*;
public class Main {
// Code for IO has been omitted.
private static final int MOD = 998244353;
private static final int maxN = 3005;
private static final long fourThird = 4 * powMod(3, MOD - 2, MOD);
private static long[] fact = new long[maxN];
private static long[] numOfInv = new long[maxN];
private static long[] sum = new long[maxN];
private static long[][] combination = new long[maxN][maxN];
public static long combination(long n, long m, int mod) {
//make it as small as possible
if (m > n - m)
m = n - m;
if (m == 0)
return 1;
long fz = 1, fm = 1;
for (int i = 1; i <= m; i++) {
fz = (fz * (n - i + 1)) % mod;
fm = (fm * i) % mod;
}
// n!/m!(n-m)!
long fmInv = powMod(fm, mod - 2, mod);
return (fz * fmInv) % mod;
}
public static long powMod(long a, long n, long mod) {
long ret = 1;
long temp = a % mod;
while (n != 0) {
if ((n & 1) != 0)
ret = ret * temp % mod;
temp = temp * temp % mod;
n >>= 1;
}
return ret;
}
public static void main(String[] args) throws Exception {
fact[0] = 1;
for (int i = 1; i < maxN; ++i)
fact[i] = fact[i - 1] * i % MOD;
for (int i = 2; i < maxN; ++i) {
numOfInv[i] = (i * numOfInv[i - 1] % MOD + fact[i - 1] * combination(i, 2, MOD) % MOD) % MOD;
sum[i] = (sum[i - 1] + numOfInv[i] * fourThird % MOD * powMod(fact[i], MOD - 2, MOD) % MOD) % MOD;
}
while (true) {
try {
int n = nextInt();
out.println((sum[n] * powMod(n, MOD - 2, MOD)) % MOD);
} catch (Exception ignored) {
out.flush();
break;
}
}
}
}