zoukankan      html  css  js  c++  java
  • UOJ514 通用测评号 和 CF891E Lust

    通用测评号

    为了实验通用测评号的实际效果,你被安排给通用测评号装填燃料。通用测评号上有 (n) 个燃料舱,初始时均为空。一个燃料舱被填满时可以储藏 (a) 单位的燃料。但为了完成本次实验,只需要每个燃料舱装填至少 (b) 单位的燃料即可。

    装填燃料是个非常无聊的事情,因此你每次会等概率随机选一个没有满的燃料舱,并且在其中放入 (1) 单位的燃料,直至所有燃料舱均包含至少 (b) 单位的燃料。

    但是由于设计上的失误,一个燃料舱被填满 (a) 单位的燃料后,该燃料舱与发动机连接的管道由于压力过大会坏掉。章北蚤发现了这个问题,他想估计坏掉的管道数量,所以想请你算一算期望有多少个燃料舱被填满了。

    为了避免实数计算带来的浮点误差,你只需要输出答案对 (998244353) 取模后的结果。

    对于所有测试数据,满足 (1 le n le 250,1 le b < a le 250)

    题解

    https://hellomath.blog.luogu.org/uoj-514

    首先发现也可以选择满了的燃料舱加燃料,这不会影响答案。

    考虑算 (1) 号燃料仓被填满时存在燃料仓燃料小于 (b) 的概率,最后再将答案乘以 (n)

    显然可以容斥。我们不妨钦定 (m) 个燃料仓燃料小于 (b) ,那么只需要关注这 (m + 1) 个燃料仓。枚举 (1) 号燃料仓被填满时其他 (m) 个燃料仓燃料有多少,那么就只需要算一个可重排列方案数(注意最后一个被填的燃料仓必须是 (1) 号):

    [sum_{0 leqslant x_1, x_2, cdots, x_m < b} igg( frac{1}{m + 1} igg)^{a + sum x_i} frac{(a - 1 + sum x_i)!}{(a - 1)! prod x_i!} ]

    枚举 (sum x_i = s) ,那么:

    [sum frac{1}{prod x_i} = [x^s] left( sum_{i = 0}^{b - 1} frac{x^i}{i!} ight)^m ]

    带上((-1)^minom{n-1}{m})的容斥系数。

    用 NTT 预处理出多项式 (F(x) = sum_{i = 0}^{b - 1} frac{x^i}{i!})(1 sim (n - 1)) 次幂即可。

    时间复杂度为 (O(n^2b log(nb)))

    CO int N=1<<16;
    int omg[2][N],rev[N];
    int fac[N],inv[N],ifac[N];
    
    void NTT(poly&a,int dir){
    	int lim=a.size(),len=log2(lim);
    	for(int i=0;i<lim;++i) rev[i]=rev[i>>1]>>1|(i&1)<<(len-1);
    	for(int i=0;i<lim;++i)if(i<rev[i]) swap(a[i],a[rev[i]]);
    	for(int i=1;i<lim;i<<=1)
    		for(int j=0;j<lim;j+=i<<1)for(int k=0;k<i;++k){
    			int t=mul(omg[dir][N/(i<<1)*k],a[j+i+k]);
    			a[j+i+k]=add(a[j+k],mod-t),a[j+k]=add(a[j+k],t);
    		}
    	if(dir){
    		int ilim=fpow(lim,mod-2);
    		for(int i=0;i<lim;++i) a[i]=mul(a[i],ilim);
    	}
    }
    poly operator*(poly a,poly b){
    	int n=a.size()+b.size()-1,lim=1<<(int)ceil(log2(n));
    	a.resize(lim),NTT(a,0);
    	b.resize(lim),NTT(b,0);
    	for(int i=0;i<lim;++i) a[i]=mul(a[i],b[i]);
    	NTT(a,1),a.resize(n);
    	return a;
    }
    
    IN int C(int n,int m){
    	return mul(fac[n],mul(ifac[m],ifac[n-m]));
    }
    int main(){
    	omg[0][0]=1,omg[0][1]=fpow(3,(mod-1)/N);
    	omg[1][0]=1,omg[1][1]=fpow(omg[0][1],mod-2);
    	fac[0]=fac[1]=1;
    	inv[0]=inv[1]=1;
    	ifac[0]=ifac[1]=1;
    	for(int i=2;i<N;++i){
    		omg[0][i]=mul(omg[0][i-1],omg[0][1]);
    		omg[1][i]=mul(omg[1][i-1],omg[1][1]);
    		fac[i]=mul(fac[i-1],i);
    		inv[i]=mul(mod-mod/i,inv[mod%i]);
    		ifac[i]=mul(ifac[i-1],inv[i]);
    	}
    	int n=read<int>(),a=read<int>(),b=read<int>();
    	int ans=0;
    	poly f(ifac,ifac+b);
    	for(int i=1;i<n;++i,f=f*poly(ifac,ifac+b)){
    		int sum=0;
    		for(int j=0,pwr=fpow(inv[i+1],a);j<=i*(b-1);++j,pwr=mul(pwr,inv[i+1]))
    			sum=add(sum,mul(f[j],mul(fac[a-1+j],pwr)));
    		sum=mul(sum,mul(ifac[a-1],C(n-1,i)));
    		if(i%2==0) sum=mod-sum;
    		ans=add(ans,sum);
    	}
    	printf("%d
    ",mul(ans,n));
    	return 0;
    }
    

    Lust

    给定 (n) 个数 (a_1,a_2,dots ,a_n) 和一个初值为 (0) 的计数器 (cnt) ,执行以下操作 (k) 次:
    (1,2,dots,n) 中等概率随机选择一个数 (i) ,令 (cnt) 加上 (prod_{j eq i}a_j),然后把 (a_i)(1) .
    (k) 次操作后计数器 (cnt) 的值的期望模 (10^9+7) .

    (nle 5 imes 10^3, kle 10^9) .

    题解

    https://jklover.hs-blog.cf/2020/06/09/CF891E-Lust/#more

    考虑每次的贡献是 (prod_{j eq i} a_j) ,然后将 (a_i) 减掉 (1) ,这可以看成是 (prod_j a_j-prod_j a_j’​) ,即减掉前后所有数乘积之差.

    (k) 次操作的贡献会抵消成 (prod a_i-prod (a_i-b_i)), 其中 (b_i) 表示 (a_i) 这个数被在 (k) 次操作中一共被减了多少次.

    前面的乘积是确定的,只用算后面那个乘积的期望,可以写出这个问题的 EGF,

    [F_a(x)=sum frac{a-i}{i!}x^i=e^x(a-x) ]

    [G(x)=prod_{i=1}^n F_{a_i}(x)=e^{nx}prod_{i=1}^n(a_i-x) ]

    所求即为 (frac{k!}{n^k}[x^k]G(x)) , 可以暴力求出 (prod_{i=1}^n(a_i-x)) 每项系数,再考虑每一项与 (e^{nx}) 卷积对答案贡献即可.

    时间复杂度 (O(n^2)) .

    CO int N=5e3+10;
    int p[N];
    
    int main(){
    	int n=read<int>(),m=read<int>();
    	int ans=1;
    	p[0]=1;
    	for(int i=1;i<=n;++i){
    		int a=read<int>();
    		ans=mul(ans,a);
    		for(int j=i-1;j>=0;--j)
    			p[j+1]=add(p[j+1],mod-p[j]),p[j]=mul(p[j],a);
    	}
    	int fac=1,inv=fpow(n,mod-2),pwr=1;
    	for(int i=0;i<=n and i<=m;++i){
    		ans=add(ans,mod-mul(mul(fac,pwr),p[i]));
    		fac=mul(fac,m-i);
    		pwr=mul(pwr,inv);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    求树的重心
    牛客多校第七场B题
    高精度
    hdu 6763 Total Eclipse 并查集+思维
    substr用法
    置换群
    快速幂
    Winform+Mysql登录
    Rider C#连接MySQL
    C# winform组件
  • 原文地址:https://www.cnblogs.com/autoint/p/13295582.html
Copyright © 2011-2022 走看看