noi.ac省选模拟赛第三场286. 集合 组合数学+期望

原题:http://noi.ac/problem/286

题解:定义F(S)=T^{min(S)},S表示1-n的子集。求E(F(S)| |S|==k ) 求长度为k的子集S,关于F(S)的期望。显然答案是\frac{\sum_{i=1}^n C_{n-i}^{k-1}*t^i}{C_{n}^k}。当k-1大于n-i时为0。这个式子就是枚举min(S)是多少,求出对应的子集个数。分母是固定,不妨我们设:A_k=\sum_{i=1}^n C_{n-i}^{k-1} t^i。这里我们需要枚举n次,又因为本题n很大,所以这么做是没有前途的。

考虑做转化,因组合数满足递推式,C_n^m=C_{n-1}^m+C_{n-1}^{m-1}

所以A_k=\sum_{i=1}^n (C_{n}^{k}-C_{n-1}^k) t^i

打开整理有:A_k=A*C_n^k+\sum _{i=1}^{n-1}C_{n-i}^k (A-1)*A^i=A*C_n^k+(A-1)*A_{k+1}

因为An=0,不妨不停的迭代整理出Ak的表达式。

即:A_k=A*(\sum_{i=0}^{n-k}(A-1)^iC_{n}^{k+1})=A*(\sum_{i=k}^{n}(A-1)^{i-k}C_{n}^{i})

由二项式定理:

\sum_{i=0}^n(A-1)^i*C_n^i=(A-1+1)^n=A^n

所以:

A_k=A*(A-1)^{-k}*(A^n-\sum_{i=0}^{k-1}(A-1)^i*C_n^i)

这样的化只用O(k)就行了。考试并没有看出递推的转换,这题真难。

#include<bits/stdc++.h>
#define ll long long 
#define M 998244353
using namespace std;
const int N=1e7+10;
ll fac[N],inv[N];
int k,n,t;
ll qpow(ll a,int b){
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%M;
		b>>=1;a=a*a%M;
	}
	return ans%M;
} 	
inline void init(){
	fac[0]=inv[0]=1;
	for(int i=1;i<=k;i++) fac[i]=fac[i-1]*i%M;
	inv[k]=qpow(fac[k],M-2);
	for(int i=k;i;i--) inv[i-1]=inv[i]*i%M; 
}
int main(){
//	freopen("a.in","r",stdin);
	scanf("%d%d%d",&n,&k,&t);
	if(t==1){
		printf("1\n");return 0;
	}
	init();
	ll ans=qpow(t,n);ll pw=1,cur=1;
	for(int i=0;i<k;i++){
		(ans-=pw*cur%M*inv[i]+M)%=M;
		cur=cur*(n-i)%M;
		pw=pw*(t-1)%M;
	}
	ans=ans*t%M*qpow(qpow(t-1,k),M-2)%M;
	ans=(ans*qpow(cur*inv[k]%M,M-2)%M+M)%M;
	printf("%lld\n",ans);
	return 0;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值