2019 Multi-University Training Contest 2. Everything Is Generated In Equal Probability

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)=nnumOfInv(n1)+(n1)!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=1ni!134numOfInv(i)=n1i=1ni!1342i!Ci2=n1i=1n32Ci2

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;
            }
        }
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值