CF1765C Card Guessing 题解

考虑期望的线性性,求每种情况猜对的概率和,最终再除掉 \({4n \choose n,n,n,n}\)

考虑枚举最少的出现次数 \(mn\),记四种卡的出现次数分别为 \(c_1,c_2,c_3,c_4\)\(c_1+c_2+c_3+c_4=i\le k\),则这种情况的方案数为:

\[{i\choose c_1,c_2,c_3,c_4}{4n-i\choose n-c_1,n-c_2,n-c_3,n-c_4}\frac{{4n-i-1\choose n-mn-1}}{{4n-i\choose n-mn}} \]

即:

\[\frac{c!}{c_1!c_2!c_3!c_4!}\frac{(4n-c-1)!\max(n-mn,1)}{(n-c_1)!(n-c_2)!(n-c_3)!(n-c_4)!} \]

做一遍背包即可,时间复杂度 \(\mathcal O(n^3)\)

参考代码:

#include<bits/stdc++.h>
#define ll long long
#define md 998244353
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
#define drep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
int n,k;
ll ans,f[2002],f1[2002],dp[503],fac[2003],ifac[2003];
ll power(ll x,int y){
	ll ans=1;
	for(;y;y>>=1){
		if(y&1)ans=ans*x%md;
		x=x*x%md;
	}
	return ans;
}
signed main(){
	fac[0]=1;
	rep(i,1,2000)fac[i]=fac[i-1]*i%md;
	ifac[2000]=power(fac[2000],md-2);
	drep(i,2000,1)ifac[i-1]=ifac[i]*i%md;
	cin>>n>>k,k=min(k,(n<<2)-1);
	drep(mn,n,0){
		rep(i,0,k)f[i]=0;
		f[0]=1;
		rept(c,0,4){
			rep(i,0,k)f1[i]=0;
			rep(i,0,k){
				rep(j,mn,min(i,n))f1[i]=(f1[i]+f[i-j]*ifac[j]%md*ifac[n-j])%md;
			}
			rep(i,0,k)f[i]=f1[i];
		}
		rep(i,0,k)dp[mn]=(dp[mn]+f[i]*fac[i]%md*fac[(n<<2)-i-1]%md*(i<k?1:(n<<2)-k))%md;
		rep(i,mn+1,n)dp[mn]=(dp[mn]-dp[i])%md;
		ans=(ans+dp[mn]*max(n-mn,1))%md;
	}
	cout<<(ans*ifac[n<<2]%md*fac[n]%md*fac[n]%md*fac[n]%md*fac[n]%md+md)%md;
	return 0;
}
posted @ 2024-04-30 17:55  zifanwang  阅读(6)  评论(0编辑  收藏  举报