長度為 n
nn 序列 a
aa 中找出 k
kk 個數加 d
dd,使新序列中如果 ai′
>aj
′a'_i>a'_j
ai′
>aj
′,那麼原序列也 a
i>aj
a_i>a_j
ai>aj
的概率。
對於每個 1≤k
≤n
1\le k\le n
1≤k≤
n,你都要輸出其對應的答案,答案模 998244353
998244353
998244
353。
等價於乙個單調上公升的序列選 k
kk 個數加 d
dd 後仍單調上公升的概率。
記 d p[
i][j
][0/
1]
dp[i][j][0/1]
dp[i][
j][0
/1] 為前 i
ii 個數選了 j
jj 個數加上 d
dd 且當前數是否選擇,滿足題意的方案數:
邊界:dp[
1][0
][0]
=dp[
1][1
][1]
=1
dp[1][0][0]=dp[1][1][1]=1
dp[1][
0][0
]=dp
[1][
1][1
]=1
狀態轉移方程:
dp[i][j][0]=dp[i-1][j][0]+dp[i-1][j][1]*(a[i-1]+d>a[i])\\ dp[i][j][1]=dp[i-1][j-1][0]+dp[i-1][j-1][1] \end
}
(kn)d
p[n]
[k][
0]+d
p[n]
[k][
1] 就是答案。
#include
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fi first
#define se second
using
namespace std;
typedef
double db;
typedef
long
long ll;
typedef pair<
int,
int> pii;
typedef vector<
int> vi;
typedef vector vpii;
//head
const
int n=
5005
;const ll mod=
998244353
;int n,d,a[n]
;ll fac[n]
,invf[n]
,dp[2]
[n][2]
;ll fpow
(ll a,ll b)
return ret;
}int
main()
fac[0]
=1;for
(int i=
1;i<=n;i++
) fac[i]
=fac[i-1]
*i%mod;
invf[n]
=fpow
(fac[n]
,mod-2)
;for
(int i=n-
1;i>=
1;i--
) invf[i]
=invf[i+1]
*(i+1)
%mod;
for(
int i=
1;i<=n;i++
)printf
("%lld\n"
,(dp[n&1]
[i][0]
+dp[n&1]
[i][1]
)%mod*fac[i]
%mod*fac[n-i]
%mod*invf[n]
%mod)
;return0;
}
牛客練習賽69D 火柴排隊 dp
n nn個數的序列,排序後讓隨機k kk個數加上d dd,求依舊滿足單調上公升的期望概率 對於乙個位置加上d dd後會讓到後面一段範圍內都得加上d dd。我們預處理乙個l il i li 表示如果i ii加上d dd後 i 1,li i 1,l i i 1,l i 都得加上ddd。然後設fi,jf ...
牛客練習賽 69
第一次打牛客直接。y1s1牛客的評測系統真的慢,搞得我不想交 題目鏈結 首先先對陣列a逆序貪心可得val i,j a1 a2 ai j val i,j a 1 a 2 dots a val i,j a 1 a 2 ai j 嘗試證明 分析可知我們最終會選擇i j i ji j個陣列a的數,貪心肯定每...
牛客練習賽69 B
題意 給定n nn個數,乙個x xx表示可以劃分成最多x xx個串,乙個y yy表示在乙個串中最多選擇y yy個數。最後求 i 1x j 1yv al i j sum x sum yval i,j i 1x j 1 y va l i,j v al i,j val i,j val i,j 為 將n n...