P6595 [YsOI2020]计划

传送门

思路

首先 \(m\) 个小朋友互相独立,我们可以计算出糖果不被他们吃掉的概率 \(q\)

为了方便记没有计划吃糖果的概率为 \(p\) (即题目中的 \(1-p\))

考虑到每颗糖果是独立的,我们可以计算出 \(1\) 颗糖果的答案,再乘以糖果数量。

因为只有一颗糖果所以概率就是期望:

\[Ans=(1-p)q^T + pqAns \]

\[Ans=\frac{(1-p)q^T}{1-pq} \]

注意到此时糖果之间相互影响,对于随机变量 \(\max\) 我们一般使用 \(\min-\max\) 容斥:

\[\begin{aligned} E(\max\{S\})&=\sum_{T \subseteq S , T \not= \varnothing} E(\min\{S\})(-1)^{|T|+1} \\ &=\sum_{i=1}^n \binom{n}{i}(-1)^{i+1} f_i \end{aligned}\]

其中 \(f_i\) 表示 \(i\) 颗糖果,最先被吃掉的糖果被吃掉的期望时间

两个重要转化:

  • 计划在 \(T\) 天后吃等价于 \(1 \sim T\) 天内只有小朋友吃, \((T+1) \sim \infty\) 天先由 TA 吃,再由小朋友吃

  • \(\displaystyle E(T)=\sum_{i \ge 1} P(T \ge i)\) , 即期望时间为大于每一个时间点的概率

现在就很好做了,不难得到:

\[f_i=1+\sum_{i=1}^T (q^i)^n + (q^T)^n\sum_{i=T+1}^{\infty} ((pq)^{i-T})^n \]

时间复杂度 \(\mathcal O(n \log n)\)

#include <cstdio>

const int MAXN = 1919820 , Mod = 998244353;
#define Add( x , y ) ( x + y >= Mod ? x + y - Mod : x + y )
#define Sub( x , y ) ( x < y ? x + Mod - y : x - y )
#define Mul( x , y ) ( (int)( 1ll * x * y % Mod ) )
int Qkpow( int x , int po ) { int p = 1; for( ; po ; po >>= 1 , x = Mul( x , x ) ) if( po & 1 ) p = Mul( p , x ); return p; } 
int Inv( int x ) { return Qkpow( x , Mod - 2 ); }
int fac[ MAXN + 5 ] , ivf[ MAXN + 5 ];
void Init() {
	fac[ 0 ] = 1;
	for( int i = 1 ; i <= MAXN ; i ++ ) fac[ i ] = Mul( fac[ i - 1 ] , i );
	ivf[ MAXN ] = Inv( fac[ MAXN ] );
	for( int i = MAXN ; i >= 1 ; i -- ) ivf[ i - 1 ] = Mul( ivf[ i ] , i ); 
}
int C( int n , int m ) { return Mul( fac[ n ] , Mul( ivf[ m ] , ivf[ n - m ] ) ); }

int n , m , T , p , q;
int Ans1 , Ans2;

int f( int n ) {
	int p1 = Qkpow( q , n ) , p2 = Qkpow( Mul( p , q ) , n );
	return 1 + Add( Mul( Mul( p1 , Sub( 1 , Qkpow( p1 , T ) ) ) , Inv( Sub( 1 , p1 ) ) ) , Mul( Qkpow( p1 , T ) , Mul( p2 , Inv( Sub( 1 , p2 ) ) ) ) );
}
int main( ) {
	Init();
	scanf("%d %d %d",&n,&m,&T);
	scanf("%d",&p); p = Sub( 1 , p ); q = 1;
	for( int i = 1 , x ; i <= m ; i ++ ) scanf("%d",&x) , q = Mul( q , Sub( 1 , x ) );
	
	Ans1 = Mul( Mul( Sub( 1 , p ) , Qkpow( q , T ) ) , Inv( Sub( 1 , Mul( p , q ) ) ) );
	for( int i = 1 ; i <= n ; i ++ ) {
		int tmp = f( i );
		if( i & 1 ) Ans2 = Add( Ans2 , Mul( C( n , i ) , tmp ) );
		else Ans2 = Sub( Ans2 , Mul( C( n , i ) , tmp ) );
	}
	printf("%d %d", Mul( Ans1 , n ) , Ans2 );
	return 0;
}
posted @ 2021-11-17 22:02  chihik  阅读(36)  评论(0编辑  收藏  举报