题解:CF1765C Card Guessing

神秘 noip 模拟赛 T3,但是 \(n\le2000\),1s。

也是终于能在模拟赛里做出数学题了,开心。

似乎没看到几个跟我一样的做法?

题解

由于期望的线性性,我们可以把期望拆分到每一位上,那么答案即为能猜对 \(c_i\) 的概率之和。

考虑如何求出猜对第 \(i\) 位的概率。下文设 \(L=\min(i-1,k)\) 为第 \(i\) 位参考的牌数。

经典的,概率转计数,问题转化为求有多少种满足第 \(i\) 位是前 \(L\) 张牌的最小值之一 的排列,对猜中第 \(i\) 张牌的贡献。

注意牌只有 \(4\) 种花色,那么可以考虑枚举所有颜色的出现次数。

钦定第 \(i\) 张牌固定且 \(c_i=1\),\(A\) 为第一种花色的出现次数,\(B,C,D\) 为剩下的花色的出现次数(无序),且 \(A\le B\le C\le D\)。那么总贡献即为(下式均有 \(A+B+C+D=L\) 的条件,只是太长了写不下):

\\\frac{L!(4n-1-L)!}{(4n-1)!} \\left( \\begin{aligned} \& \\sum\\limits_{A\

解释一下:

  • \(\sum\) 前面的系数是因为 Monocarp 会在所有最小值里面随机选择一个,所以要乘上相应的蒙对概率。

  • 为什么是 \(\binom{n-1}{A}\binom{n}{B}\binom{n}{C}\binom{n}{D}\)?因为每种颜色要从对应的花色内选取相应的次数个,而颜色 \(1\) 已经被 \(c_i\) 占用了,所以减去 \(1\)。

  • \(\sum\) 后面的系数是什么?注意,我们前面说 \(B,C,D\) 是无序的,而不同的颜色轮换对应的排列也是不同的,所以要给 \(B,C,D\) 确定它们分别代表什么颜色,于是有了这些系数。

有了这个式子,如果每个 \(i\) 暴力算,那复杂度是 \(\mathcal{O}(n^4)\),不可接受。但观察式子,我们发现 \(B,C,D\) 的组合是可以预处理的。

考虑先枚举 \(A\) 的值,那么 \(B,C,D\) 满足两个优秀条件:

  • 它们的总和固定。

  • 它们的下界固定。

那我们可以用 \(7\) 种状态表示:

  • \(\text{type}=0\):只有一个变量 \(D\)。

  • \(\text{type}=1,2\):对应 \(C<D\) 与 \(C=D\)。

  • \(3\le\text{type}\le6\):分别对应 \(B<C<D\),\(B=C<D\),\(B<C=D\),\(B=C=D\)。

定义 \(p_{\text{type},\text{sum},\text{mn}}\) 表示在状态 \(\text{type}\) 下,对应变量之和为 \(\text{sum}\),且变量下界为 \(\text{mn}\) 时,变量的组合数乘积之和。

那预处理就非常简单了。以 \(\text{type}=3\)(\(B<C<D\))为例,转移式为:

\p_{3,\\text{sum},\\text{mn}}=p_{3,\\text{sum},\\text{mn}+1}+\\binom n{\\text{mn}}\\times p_{1,\\text{sum}-\\text{mn},\\text{mn}+1} \\

理解应该不难,复杂度成功降到 \(\mathcal{O}(n^2)\),然后这题就做完了。更多具体细节可见代码。

代码

场上代码,意外的短。虽然没什么可读性就是了

cpp 复制代码
#define int long long
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define fd(i,r,l) for(int i=r;i>=l;i--)
const int mod=998244353;
template<typename T>inline T fplus(T x,T y){return x+y-(x+y>=mod?mod:0);}
template<typename T>inline T fminus(T x,T y){return x-y+(x-y<0?mod:0);}
template<typename T>inline void cplus(T&x,T y){x=fplus(x,y);}
template<typename T>inline void cminus(T&x,T y){x=fminus(x,y);}
template<typename T>inline T qp(T x,T y){T ans=1;while(y){if(y&1)ans=ans*x%mod;x=x*x%mod,y>>=1;}return ans;}

const int i2=qp(2ll,mod-2),i3=qp(3ll,mod-2),i4=qp(4ll,mod-2);
int n,k,fac[8005],inv[8005],cc[8005],ccc[8005],ans;
unsigned p[7][8005][2005];
inline int C(int x,int y){return x>y?0:fac[y]*inv[x]%mod*inv[y-x]%mod;}
//p0 x<=D
//p1 x<=C<D
//p2 x<=C=D
//p3 x<=B<C<D
//p4 x<=B=C<D
//p5 x<=B<C=D
//p6 x<=B=C=D
void solve(){
	cin>>n>>k,fac[0]=1;
	fo(i,1,4*n)fac[i]=fac[i-1]*i%mod;
	inv[4*n]=qp(fac[4*n],mod-2);
	fd(i,4*n,1)inv[i-1]=inv[i]*i%mod;
	fo(i,0,n)cc[i]=C(i,n),ccc[i]=C(i,n-1);
    
	fo(i,1,n)fd(j,min(i,n),0)
        p[0][i][j]=cc[i];
	fo(i,1,k)fd(j,min(i/2,n),0)
        p[1][i][j]=fplus(p[1][i][j+1],(unsigned)(cc[j]*p[0][i-j][j+1]%mod));
	fo(i,1,2*n)if(i%2==0)
        fd(j,i/2,0)p[2][i][j]=qp(cc[i/2],2ll);
	fo(i,1,k)fd(j,min(i/3,n),0)
        p[3][i][j]=fplus(p[3][i][j+1],(unsigned)(cc[j]*p[1][i-j][j+1]%mod));
	fo(i,1,k)fd(j,min(i/3,n),0)
        p[4][i][j]=fplus(p[4][i][j+1],(unsigned)(qp(cc[j],2ll)*p[0][i-2*j][j+1]%mod));
	fo(i,1,k)fd(j,min(i/3,n),0)
        p[5][i][j]=fplus(p[5][i][j+1],(unsigned)(cc[j]*p[2][i-j][j+1]%mod));
	fo(i,1,3*n)if(i%3==0)
        fd(j,i/3,0)p[6][i][j]=qp(cc[i/3],3ll);
    
	fo(i,1,4*n){
		int L=min(i-1,k),sum=0,tmp=0;
		fo(j,0,min(n-1,L))
			cplus(tmp,ccc[j]*p[6][L-j][j+1]%mod),//A<B=C=D 1
			cplus(tmp,3*ccc[j]*p[5][L-j][j+1]%mod),//A<B<C=D 3
			cplus(tmp,3*ccc[j]*p[4][L-j][j+1]%mod),//A<B=C<D 3
			cplus(tmp,6*ccc[j]*p[3][L-j][j+1]%mod);//A<B<C<D 6
		cplus(sum,tmp),tmp=0;
		
		fo(j,0,min(n-1,L/2))
			cplus(tmp,3*ccc[j]*cc[j]%mod*p[2][L-2*j][j+1]%mod),//A=B<C=D 3
			cplus(tmp,6*ccc[j]*cc[j]%mod*p[1][L-2*j][j+1]%mod);//A=B<C<D 6
		cplus(sum,tmp*i2%mod),tmp=0;
		
		fo(j,0,min(n-1,L/3))
			cplus(tmp,3*ccc[j]*qp(cc[j],2ll)%mod*p[0][L-3*j][j+1]%mod);//A=B=C<D 3
		cplus(sum,tmp*i3%mod);
		
		if(L%4==0)cplus(sum,qp(cc[L/4],3ll)*ccc[L/4]%mod*i4%mod);
		cplus(ans,sum*qp(C(L,4*n-1),mod-2)%mod);
	}
	cout<<ans;
}