CF1153F Serval and Bonus Problem [积分,期望]

Posted p-b-p-b

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1153F Serval and Bonus Problem [积分,期望]相关的知识,希望对你有一定的参考价值。

Codeforces

思路

去他的DP,暴力积分多好……

首先发现\(l\)没有用,所以不管它。

然后考虑期望的线性性,可以知道答案就是
\[ \int_0^1 \left[ \sum_i=k^n n\choose i(2x(1-x))^i(1-2x(1-x))^n-i\right]\mathrmdx \]
我们令
\[ y=2x(1-x) \]
暴力拆开,答案就是
\[ \int_0^1 \sum_i=K^n n\choose i \sum_j=0^n-i (-1)^j n-i\choose jy^i+j \mathrmd x \]
也就是
\[ \sum_i=K^n n\choose i \sum_j=0^n-i (-1)^j n-i\choose j 2^i+j\sum_k=0^i+j (-1)^k i+j\choose k \frac 1 i+j+k+1 \]
后面只和\(i+j\)有关,可以预处理。

然后就可以\(O(n^2)\),然后就做完了……

我才不告诉你我没有换元然后硬生生地推出了\(O(n^4)\)的式子呢

我也不会告诉你我还硬生生地把它优化成了\(O(n^3)\)

我更不会告诉你我盯着它一下午没推出来呢

代码

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std
    using namespace std;
    #define pii pair<int,int>
    #define fir first
    #define sec second
    #define MP make_pair
    #define rep(i,x,y) for (int i=(x);i<=(y);i++)
    #define drep(i,x,y) for (int i=(x);i>=(y);i--)
    #define go(x) for (int i=head[x];i;i=edge[i].nxt)
    #define templ template<typename T>
    #define sz 6000
    #define mod 998244353ll
    typedef long long ll;
    typedef double db;
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    templ inline T rnd(T l,T r) return uniform_int_distribution<T>(l,r)(rng);
    templ inline bool chkmax(T &x,T y)return x<y?x=y,1:0;
    templ inline bool chkmin(T &x,T y)return x>y?x=y,1:0;
    templ inline void read(T& t)
    
        t=0;char f=0,ch=getchar();double d=0.1;
        while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
        if(ch=='.')ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
        t=(f?-t:t);
    
    template<typename T,typename... Args>inline void read(T& t,Args&... args)read(t); read(args...);
    char __sr[1<<21],__z[20];int __C=-1,__zz=0;
    inline void Ot()fwrite(__sr,1,__C+1,stdout),__C=-1;
    inline void print(register int x)
    
        if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
        while(__z[++__zz]=x%10+48,x/=10);
        while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
    
    void file()
    
        #ifndef ONLINE_JUDGE
        freopen("a.in","r",stdin);
        #endif
    
    inline void chktime()
    
        #ifndef ONLINE_JUDGE
        cout<<(clock()-t)/1000.0<<'\n';
        #endif
    
    #ifdef mod
    ll ksm(ll x,int y)ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;
    ll inv(ll x)return ksm(x,mod-2);
    #else
    ll ksm(ll x,int y)ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;
    #endif
//  inline ll mul(ll a,ll b)ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;

using namespace my_std;

ll fac[sz],_fac[sz];
void init()_fac[0]=fac[0]=1;rep(i,1,sz-1) _fac[i]=inv(fac[i]=fac[i-1]*i%mod);
ll C(int n,int m)return n>=m&&m>=0?fac[n]*_fac[m]%mod*_fac[n-m]%mod:0;

int n,K;ll L;
ll f[sz],pow2[sz],Inv[sz];
ll ans;

int main()

    file();
    read(n,K,L);
    init();
    rep(i,1,sz-1) pow2[i]=ksm(2,i),Inv[i]=inv(i);
    rep(N,1,n) rep(k,0,N) (f[N]+=Inv[N+k+1]*((k&1)?-1ll:1ll)*C(N,k)%mod+mod)%=mod;
    rep(i,K,n) rep(j,0,n-i) (ans+=C(n,i)*((j&1)?-1ll:1ll)*C(n-i,j)%mod*pow2[i+j]%mod*f[i+j]%mod+mod)%=mod;
    cout<<ans*L%mod;
    return 0;

其他做法

这里讲一下标程的神仙DP。

考虑现在线段长度为1,那么可以发现在线段上随机丢一个点\(P\),那么\(P\)\(k\)条线段覆盖的概率就是要求的答案。

于是我们可以发现只有点之间的相对位置对答案有影响,而在线段上的位置就不重要了。

然后概率再转计数,就是要求\(2n+1\)个点,设出\(n\)个左右端点和一个\(P\),使得满足那个性质的方案数。

然后DP:\(f_i,j,x\)表示前\(i\)个点,有\(j\)个左端点还没被匹配,\(P\)有没有被放下来,的方案数。

最后考虑互换左右端点、给线段编号,答案就是
\[ \fracf_2n+1,0,1n!2^n(2n+1)! \]

以上是关于CF1153F Serval and Bonus Problem [积分,期望]的主要内容,如果未能解决你的问题,请参考以下文章

CF1153F Serval and Bonus Problem [积分,期望]

Codeforces1153F Serval and Bonus Problem 组合数

CF1153C Serval and Parenthesis Sequence

CF1153C. Serval and Parenthesis Sequence

CF1153D Serval and Rooted Tree

cf-Round551-Div2-D. Serval and Rooted Tree(DP)