zoukankan      html  css  js  c++  java
  • luogu 6046 纯粹容器 期望dp

    LINK:纯粹容器

    一道比较不错的期望题目。

    关键找到计算答案的方法。

    容易发现对于每个点单独计算答案会好处理一点。

    暴力枚举在第k轮结束统计情况 然后最后除以总方案数即可。

    考虑在第k轮的时候结束 我们要求出其所有的方案。

    首先一个点在第k轮结束必须要有一个点在第k轮和它相遇。

    如果暴力枚举这个点的话可能有不合法的方案 也不太容易进行计算。

    容易发现击败某个点的点在左边或者右边 分别设为l,r.

    考虑最后一定是 i~l或者i~r这段点都没了。

    如果l/r被击败了 也不影响解决 所以我们只关心i~l或者i~r这两端所造成的方案数。

    考虑如果是被左边击败了 设为calc(i-l,j).含义表示这i-l轮在前j轮中出现了。

    仔细分析这个东西的含义 其实i可能在前j轮中的任意一轮都出现了 但是此时我们强制其在第j轮出现 那么减掉出现在1~j-1轮的方案数即可。

    考虑calc(i-l,j)怎么计算:我的计算方法是 C(j,i-l)fac[i]C(n-1-i,j-i)fac[j-i]fac[n-1-j].

    值得一提的是 如果同时可以被两边击败那么方案为 calc(i-l,j)+calc(r-i,j)不难发现有重复的地方发生。

    即此时已经被左边击败了可是计算的确是右边的方案数反之同理 所以要减掉两边被同时击败的方案数C(r-l,j).

    const ll MAXN=300010,G=3;
    ll n;
    ll fac[MAXN],inv[MAXN],a[MAXN],w[MAXN];
    inline ll ksm(ll b,ll p)
    {
    	ll cnt=1;
    	while(p)
    	{
    		if(p&1)cnt=(ll)cnt*b%mod;
    		b=(ll)b*b%mod;
    		p=p>>1;
    	}
    	return cnt;
    }
    inline ll C(ll a,ll b){if(a<b)return 0;return fac[a]*inv[b]%mod*inv[a-b]%mod;}
    inline ll calc(ll i,ll j){if(j<i)return 0;return C(j,i)*C(n-1-i,j-i)%mod*fac[i]%mod*fac[j-i]%mod;}
    signed main()
    {
    	freopen("1.in","r",stdin);
    	get(n);fac[0]=1;
    	rep(1,n,i)get(a[i]),fac[i]=fac[i-1]*i%mod;
    	inv[n]=ksm(fac[n],mod-2);
    	fep(n-1,0,i)inv[i]=inv[i+1]*(i+1)%mod;
    	//cout<<calc(1,2)<<endl;
    	rep(1,n,i)
    	{
    		ll l=0,r=0,ans=0;
    		fep(i-1,1,j)if(a[j]>a[i]){l=j;break;}
    		rep(i+1,n,j)if(a[j]>a[i]){r=j;break;}
    		if(!l&&!r){printf("%d ",n-1);continue;}
    		int las=0;
    		rep(1,n-1,j)
    		{
    			if(!l)
    			{
    				ans=(ans+((calc(r-i,j)*fac[n-1-j])-las)%mod*(j-1))%mod;
    				las=(calc(r-i,j)*fac[n-1-j])%mod;
    				//putl(calc(r-i,j));//putl(calc(r-i,j-1));
    			}
    			if(!r)
    			{
    				ans=(ans+(calc(i-l,j)*fac[n-1-j]-las)%mod*(j-1))%mod;
    				las=calc(i-l,j)*fac[n-1-j]%mod;
    			}
    			if(l&&r)
    			{
    				ans=(ans+((calc(i-l,j)+calc(r-i,j)-calc(r-l,j))*fac[n-1-j]-las)%mod*(j-1))%mod;
    				las=((calc(i-l,j)+calc(r-i,j)-calc(r-l,j))*fac[n-1-j])%mod;
    			}
    		}
    		ans=ans*inv[n-1]%mod;
    		printf("%lld ",(ans+mod)%mod);
    	}
    	return 0;
    }
    
  • 相关阅读:
    React antd如何实现<Upload>组件上传附件再次上传已清除附件缓存问题。
    spring项目logback日志与logstash和Elasticsearch整合
    Java后端面试经验总结分享(一)
    【设计模式】访问者模式
    【设计模式】命令模式
    【设计模式】模板方法模式
    【设计模式】代理模式
    【设计模式】享元模式
    【设计模式】外观模式
    【设计模式】组合模式
  • 原文地址:https://www.cnblogs.com/chdy/p/12774506.html
Copyright © 2011-2022 走看看