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;
    }
    
  • 相关阅读:
    Head first javascript(七)
    Python Fundamental for Django
    Head first javascript(六)
    Head first javascript(五)
    Head first javascript(四)
    Head first javascript(三)
    Head first javascript(二)
    Head first javascript(一)
    Sicily 1090. Highways 解题报告
    Python GUI programming(tkinter)
  • 原文地址:https://www.cnblogs.com/chdy/p/12774506.html
Copyright © 2011-2022 走看看