Loading

[MtOI2019]时间跳跃

\([MtOI2019]\)时间跳跃

链接:https://www.luogu.com.cn/problem/P5615

题目描述:机关有\(n\)条秘密通道,第\(i\)条秘密通道的长度为\(i\),机关会从所有选择方式种等概率随机选出一些秘密通道,如果选出来的这些秘密通道能组成一个凸多边形,那么这个方案的权值就是选出的秘密通道数量,否则权值为\(0\)
那么请你求出选出来秘密通道的权值的期望。

题解:首先我们知道题目要求的是秘密通道的权值之和,这样才能算期望。

通过容斥可得:总共的\(-\)不合法的\(=\)要求的

总共的可以枚举选了多少个,拿组合数算,预处理阶乘逆元即可。

求不合法的,其实就是要求对于每一个数,和等于它的数列的大小之和,令两个\(dp\)数组分别表示和等于\(i\)的数列的大小之和,和等于i的数列的总数,背包转移即可。统计总数时可以处理\(dp\)的前缀和。

#include<iostream>
#define mod 1000000007
using namespace std;
long long fac[5001],invfac[5001],f[5001],s[5001],d[5001],t[5001],n;
long long fast_pow(long long a,long long b)
{
	if (b==0)
		return 1;
	if (b&1)
		return fast_pow(a*a%mod,b/2)*a%mod;
	else
		return fast_pow(a*a%mod,b/2); 
}
long long C(long long a,long long b)
{
	return fac[b]*invfac[b-a]%mod*invfac[a]%mod;
}
int main()
{
	d[0]=1;
	for (int i=1;i<=5000;++i)
		for (int j=5000;j>=i;--j)
			{
				d[j]+=d[j-i];
				s[j]+=(s[j-i]+d[j-i])%mod;
				d[j]%=mod;
				s[j]%=mod;
			}
	fac[0]=1;
	for (int i=1;i<=5000;++i)
		fac[i]=fac[i-1]*i%mod;
	invfac[5000]=fast_pow(fac[5000],mod-2);
	for (int i=4999;i>=0;--i)
		invfac[i]=invfac[i+1]*(i+1)%mod;
	for (int i=1;i<=5000;++i)
		for (int j=1;j<=i;++j)
		{
			f[i]+=(C(j,i)*j%mod);
			f[i]%=mod;
		}
	d[0]=0;
	for (int i=1;i<=5000;++i)
		s[i]=(s[i]+s[i-1])%mod;
	for (int i=1;i<=5000;++i)
		d[i]=(d[i]+d[i-1])%mod; 
	for (int i=1;i<=5000;++i)
		t[i]=((t[i-1]+s[i]+d[i]-1)%mod+mod)%mod;
	int q;
	cin>>q;
	for (int i=1;i<=q;++i)
	{
		cin>>n;
		cout<<((f[n]-t[n])%mod+mod)%mod*fast_pow(fast_pow(2,n),mod-2)%mod<<endl;
	}
	return 0; 
}
posted @ 2022-12-14 21:18  zhouhuanyi  阅读(76)  评论(0)    收藏  举报