CF1765C Card Guessing 做题记录
CF1765C Card Guessing
Description
有 \(4\) 种花色的牌,每种牌均为 \(n\) 张,则牌的排列⼀共有 \((4\cdot n)!\) 种。
现在你从牌堆中逐张地取出牌,取牌之前你都会猜这张牌是什么花色。你会根据之前的 \(k\) 张牌中出现最少的花色来猜这张牌。
如果有多种花色都是最少的,你随机地猜一种。
如果之前抽出的牌不足 \(k\) 张,就按之前的所有牌中的最少花色来猜。
问你猜对的期望次数是多少?
Solution
令 \(m=4n\)。设 \(m\) 个随机变量 \(X_1,X_2,...X_m\),\(X_i\) 取值为 \(1\) 表示第 \(i\) 次猜对,否则没有猜对。
那么我们求的是:
独立地求出每一次猜对的概率,加和即为答案。
设 \(L=\min(i-1,k)\),我们称之前的 \(L\) 张牌为 “依据牌”。首先有一个比较重要的观察:在依据牌中存在多种最少的花色时,无论猜哪一个花色,猜对概率都是一样的。
原因很简单,在依据牌固定的情况下,设它们在依据牌中出现的次数为 \(c\),那么下面一张牌猜对的概率都是 \(\dfrac{n-c}{m-L}\)。
考虑概率转计数。那么题意转化为:
- 对每一个 \(i \ (1\leq i \leq m)\) 求:有多少个序列,使得 \(i\) 的花色为 \(A_{i-L} \sim A_{i-1}\) 中出现次数最少的花色。 若有多种最少的花色,则令 \(i\) 为最少的花色中编号最小的。
首先考虑如何计算答案。设这 \(L+1\) 张牌组成的序列数量为 \(B\),那么对应的概率为:
现在我们的答案只和这 \(L+1\) 张牌有关。
枚举这 \(L\) 张牌中出现次数最少的花色出现了几次。由于每个花色出现个数被 \(n\) 限制,不易直接用组合数求解,那么考虑 dp 求解:
设 \(f_{i,j,l}\) 表示考虑到第 \(i\) 种花色,选了 \(j\) 张牌,最小出现花色为 \(l\) 的方案数。
我们选择下一种花色分为三步:
- 在 \(n\) 张牌中选择 \(t\) 张;
- 对这 \(t\) 张牌进行排列;
- 将这 \(t\) 张牌插入到已经选好的 \(j\) 张牌中。
得出转移:
这个部分复杂度为 \(O(n^3)\)。
对于一个 \(L\),枚举依据牌中出现最少的花色的出现次数 \(l\),那么后面的 \(i\) 就有 \(n-l\) 种选择。那么得到 \(i\) 猜对的序列个数为:
这个部分复杂度为 \(O(n^2)\)。
由于第 \(1\) 张牌前没有依据牌,需要单独计算。最终的答案为:
int n,k,m;
const ll mod=998244353;
ll Mod(ll x){return (x>=mod)?(x-mod):(x);}
void Add(ll &x,ll y){x=Mod(x+y);}
ll f[6][M][M],fac[M],caf[M],g[M],h[M];
ll QuickPow(ll x,ll y){
ll res=1;
while(y){
if(y&1) res=res*x%mod;
x=x*x%mod; y>>=1;
}
return res;
}
void Init(){
fac[0]=caf[0]=1;
for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
caf[m]=QuickPow(fac[m],mod-2);
for(int i=m-1;i;i--) caf[i]=caf[i+1]*(i+1)%mod;
}
ll C(int x,int y){
if(x<0||y<0||x<y) return 0;
return fac[x]*caf[y]%mod*caf[x-y]%mod;
}
signed main(){
read(n),read(k); m=n<<2;
Init();
for(int i=0;i<=m;i++) f[1][i][i]=C(n,i)*fac[i]%mod;
for(int i=1;i<=3;i++){
for(int j=0;j<=m;j++){
for(int l=0;l<=j;l++){
if(!f[i][j][l]) continue;
for(int t=0;t<=n&&j+t<=m;t++){
Add(f[i+1][j+t][min(l,t)],f[i][j][l]*C(n,t)%mod*C(j+t,t)%mod*fac[t]%mod);
}
}
}
}
for(int i=1;i<=m;i++){
for(int j=0;j<=n;j++){
Add(g[i],f[4][i][j]*(n-j)%mod);
Add(h[i],f[4][i][j]);
}
}
ll ans=QuickPow(4,mod-2);
for(int i=2;i<=m;i++){
int j=min(i-1,k);
ll H=C(m,j+1)*fac[j+1]%mod;
ll inv=QuickPow(H,mod-2);
Add(ans,g[j]*inv%mod);
}
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号