zoukankan      html  css  js  c++  java
  • [AGC038E] Gachapon

    VI.[AGC038E] Gachapon

    因为模型同III.重返现世长得很像,所以我们也来考虑minmax容斥。

    首先,我们仍然翻出式子

    [max(mathbb S)=sumlimits_{mathbb{Tsubseteq S}}(-1)^{|mathbb T|+1}min(mathbb T) ]

    然后,我们考虑计算 ( ext E(minmathbb T))

    我们发现,对于某个 (mathbb T),它的 (min) 的实际意义是其中一个元素率先全部被生成。而当该元素被生成完时,其它 (mathbb T) 中元素生成的数量都不能达到 (b_i)。因此这启发我们要枚举结束时 (mathbb T) 中每个元素被生成的数量。设此数组为 ({c})

    我们发现,由 (mathbb T) 来推出所有合法的 ({c}) 是困难的,但是由 ({c}) 来反推 (mathbb T) 则是简单的——因为在处理 ({c}) 的时候肯定顺手就把 (mathbb T) 的位置给记录了。于是我们考虑给定了一个 ({c}),计算其作为其对应的 (mathbb T) 的终止状态的概率。

    首先,我们考虑令 (a') 表示那个率先被全部生成的数的 (a)。显然,(c'=b'),但是因为钦定了最后一个生成的数是 (a'),因此我们令 (c') 强制减一,这样现在所有 (c) 中元素间顺序便可以任意调换。

    考虑恰好生成 (c) 中所有元素的概率,是

    [dfrac{prod a^c}{(sum a)^{sum c}} ]

    但是,因为元素间有序,所以还要乘上多项式系数

    [dfrac{(sum c)!}{prod c!} ]

    同时,别忘记最后一个生成的数必须是 (a'),因此还有

    [dfrac{a'}{sum a} ]

    考虑生成此种情形期望需要生成多少个数:因为期望 (dfrac{S}{sum a})(依照题面,有定义 (S=sumlimits_{i=0}^{n-1}a_i))次会摇到一个来自 (mathbb T) 中的元素,所以期望 ((sum c+1) imesdfrac S{sum a}) 次就能摇全。

    所有东西怼一块,得到

    [(sum c+1) imesdfrac S{sum a} imesdfrac{prod a^c}{(sum a)^{sum c}} imesdfrac{(sum c)!}{prod c!} imesdfrac{a'}{sum a} ]

    稍微整理一下,把与单个的 (a)(sum a) 有关的拆开来放

    [S imesdfrac{(sum c+1) imes(sum c)!}{(sum a)^{sum c+2}} imesdfrac{prod a^c imes a'}{prod c!} ]

    最开头的是常数,中间一个分数是与 (sum c,sum a) 有关的东西,最后一坨是与单个的 (a)(c) 有关的东西。

    于是我们考虑DP。设 (f_{i,j,k,odd,0/1}) 表示当前DP到位置 (i)(sum c=j,sum a=k)(|mathbb T|) 的奇偶性为 (odd),且 (a') 未/已被决定。

    转移分两种:确定 (a') 的转移和不确定 (a') 的转移。确定 (a') 的转移就强制你有 (c=b-1)(注意到我们之前已经令 (c') 强制减一了),不确定 (a') 的转移,可以枚举 (cin[0,b))

    乍一看,(i,j,k) 三维都是 (400),剩下两维都是常数,但还要枚举一个 (c),这不是 (400^4) 的吗?

    一开始我也苦恼了很久,但后来想到 (i) 维和 (c) 维加在一块等于 (sum b=400),因此实际是 (400^3) 的。

    注意将一些共同的东西提前算出可以减少常数。

    代码:

    #include<bits/stdc++.h> 
    using namespace std;
    const int mod=998244353;
    int ksm(int x,int y=mod-2){int z=1;for(;y;y>>=1,x=1ll*x*x%mod)if(y&1)z=1ll*z*x%mod;return z;}
    int n,a[410],b[410],A,B,f[410][410][2][2],fac[410],inv[410],res;
    void ADD(int &x,int y){x+=y;if(x>=mod)x-=mod;}
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]),A+=a[i],B+=b[i];
    	fac[0]=1;for(int i=1;i<=B;i++)fac[i]=1ll*fac[i-1]*i%mod;
    	inv[B]=ksm(fac[B]);for(int i=B;i;i--)inv[i-1]=1ll*inv[i]*i%mod;
    //	for(int i=0;i<=B;i++)printf("%d ",fac[i]);puts("");
    //	for(int i=0;i<=B;i++)printf("%d ",inv[i]);puts("");
    	f[0][0][0][0]=1;
    	for(int i=1;i<=n;i++){
    		int tmp=1ll*ksm(a[i],b[i]-1)*inv[b[i]-1]%mod*a[i]%mod;
    		for(int j=B;j>=0;j--)for(int k=A;k>=0;k--)for(int odd=0;odd<2;odd++){
    	//		if(f[j][k][odd][0])printf("(%d,%d,%d,%d,%d):%d
    ",i-1,j,k,odd,0,f[j][k][odd][0]);
    	//		if(f[j][k][odd][1])printf("(%d,%d,%d,%d,%d):%d
    ",i-1,j,k,odd,1,f[j][k][odd][1]);
    			if(f[j][k][odd][0]){
    	//			printf("%d %d %d %d
    ",f[j][k][odd][0],ksm(a[i],b[i]-1),inv[b[i]-1],a[i]);
    				ADD(f[j+b[i]-1][k+a[i]][odd^1][1],1ll*f[j][k][odd][0]*tmp%mod);
    				for(int l=0,m=1;l<b[i];l++,m=1ll*m*a[i]%mod)ADD(f[j+l][k+a[i]][odd^1][0],1ll*f[j][k][odd][0]*m%mod*inv[l]%mod);
    			}
    			if(f[j][k][odd][1])for(int l=0,m=1;l<b[i];l++,m=1ll*m*a[i]%mod)ADD(f[j+l][k+a[i]][odd^1][1],1ll*f[j][k][odd][1]*m%mod*inv[l]%mod);
    		}	
    	}
    	for(int j=0;j<=B;j++)for(int k=1;k<=A;k++)for(int odd=0;odd<2;odd++){
    		int tmp=1ll*f[j][k][odd][1]*(j+1)%mod*A%mod*ksm(ksm(k,j+2))%mod*fac[j]%mod;
    //		printf("%d,%d,%d:%d
    ",j,k,odd,tmp);
    //		printf("%d %d %d %d %d
    ",f[j][k][odd][1],(j+1),A,ksm(ksm(k,j+2)),fac[j]);
    		if(odd&1)(res+=tmp)%=mod;else (res+=mod-tmp)%=mod;
    	}
    	printf("%d
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    do-while-zero 结构在宏定义中的应用
    关于运放的几个概念
    Spring MVC 学习第一篇
    1229递归下降
    有限自动机的构造与识别
    11.11评论
    文法分析2
    文法分析
    201406114215+林志杰+文法分析
    词法分析实验总结
  • 原文地址:https://www.cnblogs.com/Troverld/p/14636966.html
Copyright © 2011-2022 走看看