9.28T2 组合数学+容斥原理+sigma优化
期望(mex)
【题目背景】
NOI2018 已经过去了许久,2019 届的 BSOIer 们退役的退役,颓废的颓废,计数能 力大不如前。
曾经的数数之王 xxyj 坦言:“我现在算期望都靠枚举”,嘴边还挂着什么 “分布列”,什么“样本数据”,然后又继续投身于文化课学习中了。
为了让 OI 的火炬传递下去,苣蒻 AChen 决定将 xxyj 退役前随口提到的期望问题 交给你来解决。
【题目描述】
现有 m + 1 个白色的小球排成一列并从一开始编号。
每次操作从前 m 个小球中随 机选择一个涂黑。
现在执行了 n 次操作,则编号最小的白球编号的期望是多少?
【输入格式】
从文件 mex.in 中读入数据。
输入共一行两个整数 n,m 表示操作次数和白色小球的个数。
【输出格式】
输出到文件 mex.out 中。
若最小的白球编号的期望为 E,则输出一行表示:
可以看出上式一定是个整数。
【样例 1 输入】
1 1
【样例 1 输出】
2
【样例 1 解释】
不难验证结果的正确性。
首先球可以反复涂(我考试就是以为只能涂一次于是GG)
首先答案ans是
P(i)表示在m个球中涂上前 i 个小球的方案,不难证明这可以组成所有组合
所以我们的目标现在变成了求每个P( i )了,这就分割成了子问题
那么我们怎么求出涂了前 i 个球的方案呢?首先因为有重复涂并且这个是一个分开的问题,还是不可以直接求解
那么我们一般的套路是:求前i个有,那么总体减掉容斥至少1,2,3,4....个没有的情况。为什么要容斥?因为至少x个包含了x+1,统计另一个的时候又会重复
所以不难得出公式:
所以ans也就出来了:
至此整道题就结束了
注意爆long long,代码不长,不清楚的请评论下
套路下来感觉NOIP可考
code:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const long long mod=1e9+7; 5 long long n,m; 6 long long mo[1000005],inv[1000005]; 7 long long power(long long a,long long b){ 8 long long t=a,ans=1; 9 for(;b;b>>=1){ 10 if(b&1){ 11 ans*=t; 12 ans%=mod; 13 } 14 t*=t;t%=mod; 15 } 16 return ans; 17 } 18 void pre(){//计算阶乘的逆元 19 mo[0]=mo[1]=1; 20 for(long long i=2;i<=m+1;i++) 21 mo[i]=(mo[i-1]*i)%mod; 22 inv[m+1]=power(mo[m+1],mod-2); 23 for(long long i=m;i>=0;i--) 24 inv[i]=inv[i+1]*(i+1)%mod; 25 } 26 int main(){ 27 freopen("mex.in","r",stdin); 28 freopen("mex.out","w",stdout); 29 cin>>n>>m; 30 pre(); 31 long long ans=0; 32 for(long long k=0;k<=m;k++){ 33 if(k&1) ans-=((power(m-k,n)%mod)*(mo[m+1]*inv[k+1]%mod*inv[m-k]%mod)%mod)%mod; 34 else ans+=((power(m-k,n)%mod)*(mo[m+1]*inv[k+1]%mod*inv[m-k]%mod)%mod)%mod; 35 ans=(ans+mod)%mod; 36 } 37 cout<<(ans+mod)%mod; 38 return 0; 39 }
over