AGC050D

· · 题解

一年前觉得不太可做的题。

我们要算什么?每个人能拿物品的概率,所以 dp 的状态值肯定是某种概率。

事实上,如果一个人领到了物品,我们直接当成把他删掉,显然不影响答案。

考虑没有领到的物品的人,令当前是第 x 轮,显然他试过 x-1 个物品,那么就是在 k-(x-1) 个物品里随机选。

我们令现在剩下 m 个人,那么就只有 k-m 个物品是未选的,当前这个人能领到物品的概率就是 (k-m)/(k-x+1)

我们就针对一个人能选到的概率设计 dp

转移简单,复杂度 $O(n^4)$ 。 ```cpp #include<bits/stdc++.h> using namespace std; int n,m,inv[60]; const int mod=998244353; int dp[50][50][50][50]; int dfs(int x,int y,int z,int w){ if(dp[x][y][z][w]!=-1)return dp[x][y][z][w]; if(w>m||n-(x+y+1)>=m)return 0; int I=inv[m-w+1],p=1ll*(m-n+x+y+1)*I%mod; int as; if(z==x+1) as=(p+1ll*(1-p)*(y?dfs(x,y,z+1,w):dfs(x,y,1,w+1))%mod)%mod; else if(z<=x)as=(1ll*p*dfs(x-1,y,z,w)%mod+1ll*(1-p)*dfs(x,y,z+1,w)%mod)%mod; else{ if(z==x+y+1)as=(1ll*p*dfs(x,y-1,1,w+1)%mod+1ll*(1-p)*dfs(x,y,1,w+1)%mod)%mod; else as=(1ll*p*dfs(x,y-1,z,w)%mod+1ll*(1-p)*dfs(x,y,z+1,w)%mod)%mod; } return dp[x][y][z][w]=(as+mod)%mod; } int main(){ inv[1]=1; for(int i=2;i<=55;i++)inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod; cin>>n>>m; memset(dp,-1,sizeof(dp)); for(int i=1;i<=n;i++) printf("%d\n",dfs(i-1,n-i,1,1)); return 0; } ```