QOJ20075 Ascending Random Number Sequence 题解
法 1:
首先有 \(E=\frac{1}{n}\sum_{k=1}^n E_k\),其中 \(E_k\) 表示在限制为 \(k\) 的时候长度的期望。
有 DP 转移式,设 \(f_i\) 表示当前填的最后一个数是 \(i\) 的时候期望还要填多少次,则 \(E_k=f_0\)。\(f_i=1+\frac{\sum_{x=i+1}^{k-1} f_x}{n-i}\)。
设 \(s_i=\sum_{j=i}^{k-1}f_j\),则有 \(s_{i}=f_i+s_{i+1}\),又得 \(f_i=1+\frac{s_{i+1}}{n-i}\),带入得 \(s_i=1+\frac{n-i+1}{n-i} \times s_{i+1}\),左右同除 \(n-i+1\),得 \(\frac{s_i}{n-i+1}=\frac{1}{n-i+1}+\frac{s_{i+1}}{n-i}\),设 \(a_i=\frac{s_i}{n-i+1}\)。最后推导可得 \(E_k=1+\sum_{i=n-k+2}^n \frac{1}{i}\)。因为调和级数 \(H_n\) 有性质 \(\sum_{i=1}^n H_i=(n+1)H_n-n\),所以答案是 \(2-\frac{H_n}{n}\)。
法 2:
先随机生成一个排列,答案为所有数进入序列的概率之和。一个数进入序列的概率就是在生成的全排列中是前缀最大值的概率以及它合法的概率。\(j\) 是前缀最大值相当于在 \(j,j+1,\dots,n\) 的排列顺序中在最前面,为 \(\frac{1}{n-j+1}\)。如果 \(j < k\),一定合法,如果大于等于 \(k\),则必须是第一个大于等于 \(k\) 的数,所以概率为 \(\frac{1}{n-k+1}\)。
那总的答案就是 \(E_k=\sum_{j=1}^{k-1} \frac{1}{n-j+1}+\sum_{j=k}^{n} \frac{1}{n-k+1}\),即 \(H_n-H_{n-k+2}+1\)。求和之后还是一样的结果。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define popcount(x) __builtin_popcount(x)
int n;
const int N = 1e7+10,mod=998244353;
ll qpow(ll a,int b){
ll res=1;
while(b){
if(b&1)res=(1ll*res*a)%mod;
a=(1ll*a*a)%mod;
b>>=1;
}
return res;
}
int fac[N],inv[N];
signed main(){
cin>>n;
fac[0]=1;
for(int i=1;i<=n;i++){
fac[i]=(1ll*fac[i-1]*i)%mod;
}
inv[n]=qpow(fac[n],mod-2);
for(int i=n-1;i>=0;i--){
inv[i]=(1ll*inv[i+1]*(i+1)%mod)%mod;
}
for(int i=2;i<=n;i++){
inv[i]=(1ll*inv[i]*fac[i-1])%mod;
}
ll Hn=0;
for(int i=1;i<=n;i++){
Hn=(Hn+inv[i])%mod;
}
ll ans=(2-Hn%mod*inv[n]%mod+mod)%mod;
cout<<ans;
return 0;
}

浙公网安备 33010602011771号