排列最小值 [期望]

排 列 最 小 值 排列最小值


正 解 部 分 \color{red}{正解部分}

首先排列中第 i i i 个元素作为前 i i i 个元素的最小值的概率为 1 i \frac{1}{i} i1,

f [ i ] f[i] f[i] 表示排列第 i i i 个元素是否为前 i i i 个元素的最小值, 值为 0 / 1 0/1 0/1,
根据题目要求, 期望为 a n s = ( ∑ i = 1 n f [ i ] ) 2 = ∑ i = 1 n ∑ j = 1 n f [ i ] f [ j ] ans = \left( \sum\limits_{i=1}^n f[i] \right)^2 = \sum\limits_{i=1}^n \sum\limits_{j=1}^n f[i]f[j] ans=(i=1nf[i])2=i=1nj=1nf[i]f[j],

i = j i = j i=j 时, f [ i ] f [ j ] = 1 f[i]f[j] = 1 f[i]f[j]=1 的概率为 1 i \frac{1}{i} i1, 在上式对期望的贡献为 ∑ i = 1 n 1 i \sum\limits_{i=1}^n \frac{1}{i} i=1ni1 .
i   ! = j i\ != j i !=j 时, f [ i ] f [ j ] = 1 f[i]f[j] = 1 f[i]f[j]=1 的概率为 1 i × 1 j \frac{1}{i} \times \frac{1}{j} i1×j1,
在上式对期望的贡献为 ∑ i = 1 n 1 i ( ( ∑ j = 1 n 1 j ) − 1 i ) = ( ∑ i = 1 n 1 i ) 2 − ∑ i = 1 n 1 i 2 \sum\limits_{i=1}^n \frac{1}{i}\left( (\sum\limits_{j=1}^n \frac{1}{j}) - \frac{1}{i}\right) = \left(\sum\limits_{i=1}^n\frac{1}{i}\right)^2 - \sum\limits_{i=1}^n \frac{1}{i^2} i=1ni1((j=1nj1)i1)=(i=1ni1)2i=1ni21 .

所以 a n s ans ans 的期望为 ∑ i = 1 n 1 i + ( ∑ i = 1 n 1 i ) 2 − ∑ i = 1 n 1 i 2 \sum\limits_{i=1}^n \frac{1}{i}+\left(\sum\limits_{i=1}^n\frac{1}{i}\right)^2 - \sum\limits_{i=1}^n \frac{1}{i^2} i=1ni1+(i=1ni1)2i=1ni21,

然后使用 a n s ans ans 乘上 n ! n! n! 即为题目中的答案 .


实 现 部 分 \color{red}{实现部分}

#include<bits/stdc++.h>
#define reg register

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 1e5 + 10;
const int mod = 998244353;

int N;
int Q_;
int inv[maxn];
int fac[maxn];
int sum_1[maxn];
int sum_2[maxn];

void Work(){
        N = read();
        int Ans = (sum_1[N] - sum_2[N] + mod) % mod;
        Ans = (1ll*Ans + (1ll*sum_1[N]*sum_1[N]%mod)) % mod;
        Ans = 1ll*Ans*fac[N] % mod;
        printf("%d\n", Ans);
}

int main(){
        Q_ = read();
        fac[0] = 1; for(reg int i = 1; i < maxn; i ++) fac[i] = 1ll*fac[i-1]*i % mod;
        inv[1] = 1; for(reg int i = 2; i < maxn; i ++) inv[i] = ((-1ll*mod/i*inv[mod%i])%mod + mod) % mod;
        for(reg int i = 1; i < maxn; i ++){
                sum_1[i] = (sum_1[i-1] + inv[i]) % mod;
                sum_2[i] = (sum_2[i-1] + (1ll*inv[i]*inv[i]%mod)) % mod;
        }
        while(Q_ --) Work();
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值