题目大意:
给定一个无穷大的
k
叉树,从根节点向下走,每个分支的点权为
0
至
k
−
1
,
求满足下列要求的概率
,
答案取模
998244353
给定一个无穷大的k叉树,从根节点向下走,每个分支的点权为0至k-1,求满足下列要求的概率,答案取模998244353
给定一个无穷大的k叉树,从根节点向下走,每个分支的点权为0至k−1,求满足下列要求的概率,答案取模998244353
1.
从根节点到该点所经过的所有点的点权和为
n
1.从根节点到该点所经过的所有点的点权和为 n
1.从根节点到该点所经过的所有点的点权和为n
2.
从根节点到该点所经过的所有点权所构成的序列非递减。
2.从根节点到该点所经过的所有点权所构成的序列非递减。
2.从根节点到该点所经过的所有点权所构成的序列非递减。
题目分析:
可以设
d
p
x
,
d
表示经过的点权和为
x
,
上一个点的点权为
d
,继续走,合法的概率
可以设dp_{x,d}表示经过的点权和为x,上一个点的点权为d,继续走,合法的概率
可以设dpx,d表示经过的点权和为x,上一个点的点权为d,继续走,合法的概率
首先不难想到转移式
d
p
x
,
d
=
∑
i
=
d
k
−
1
d
p
x
+
i
,
i
∗
1
k
,
首先不难想到转移式dp_{x,d}=\sum_{i=d}^{k-1}dp_{x+i,i}*\frac{1}{k},
首先不难想到转移式dpx,d=∑i=dk−1dpx+i,i∗k1,
答案便为
d
p
0
,
0
,
但是观察转移式会发现,当
d
=
0
时,转移式便存在一个问题,会无限递归
,
我们不妨在
d
=
0
且
x
>
0
时不进行转移,最后再转移
答案便为dp_{0,0},但是观察转移式会发现,当d=0时,转移式便存在一个问题,会无限递归,我们不妨在d=0且x>0时不进行转移,最后再转移
答案便为dp0,0,但是观察转移式会发现,当d=0时,转移式便存在一个问题,会无限递归,我们不妨在d=0且x>0时不进行转移,最后再转移
当 d = 0 , x = 0 时 d p 0 , 0 = ∑ i = 0 k − 1 d p 0 + i , i ∗ 1 k , 将等式右边的 d p 0 , 0 ∗ 1 k 移项至左边,得 k − 1 k d p 0 , 0 = 1 k ∗ ∑ i = 1 k − 1 d p 0 + i , i , 故 d p 0 , 0 = 1 k − 1 ∗ ∑ i = 1 k − 1 d p 0 + i , i 当d=0,x=0时 dp_{0,0}=\sum^{k-1}_{i=0}dp_{0+i,i}*\frac{1}{k},将等式右边的dp_{0,0}*\frac{1}{k}移项至左边,得\frac{k-1}{k}dp_{0,0}=\frac{1}{k}*\sum^{k-1}_{i=1}dp_{0+i,i}, 故dp_{0,0}=\frac{1}{k-1}*\sum^{k-1}_{i=1}dp_{0+i,i} 当d=0,x=0时dp0,0=∑i=0k−1dp0+i,i∗k1,将等式右边的dp0,0∗k1移项至左边,得kk−1dp0,0=k1∗∑i=1k−1dp0+i,i,故dp0,0=k−11∗∑i=1k−1dp0+i,i
参考代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int M=207;
const LL Mod=998244353;
int n,k;
LL dp[M][M];
LL qpow(LL x,LL tim){
LL ret=1,tmp=x;
while(tim){
if(tim&1) ret=ret*tmp%Mod;
tmp=tmp*tmp%Mod;
tim>>=1;
}
return ret;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=0;i<k;i++){
dp[n][i]=1;
}
for(int x=n;x>=0;x--){
for(int d=1;d<=k;d++){
for(int l=d;l<k;l++){
dp[x][d]=(dp[x][d]+dp[l+x][l]*qpow(k,Mod-2))%Mod;
}
}
}
for(int i=1;i<k;i++){
dp[0][0]=(dp[0][0]+dp[i][i])%Mod;
}
dp[0][0]=(qpow(k-1,Mod-2)*dp[0][0])%Mod;
cout<<dp[0][0]<<"\n";
}