zoukankan      html  css  js  c++  java
  • [ZJOI2019]开关

    [ZJOI2019]开关 

    题解

    到了就停止,很麻烦,因为要状压

    走了i步,还没有停止方案数,再除以概率,还是不行,还要状压

    所以干脆反演(容斥?)直接求i步之后停止的概率,不管之前有没有停止,然后进行反演

    概率生成函数

    1.每个开关的EGF

    OGF:j开关的x^i的系数定义为:操作了i次,都操作到了j,并且到达了目标状态的概率

    EGF:额外除以i!,为了之后多重集合排列用,可以直接用e代替

    2.总共的EGF

    直接把每个EGF乘起来

    这一步可以背包得到e^(ix)的系数a

    3.反演,

    要求的生成函数OGF是h,这样h'(1)就是答案

    而g*h=f,h=f/g

    g就是si=0的状态下的OGF(等价于绕环)

    EGF和OGF的转化?就是每一位乘上i!

    把e麦克劳林展开,直接乘上i!即可

    计算h'(1)要用到f'(1),g'(1),f(1),g(1)

    但是可能1-vx=0

    4.通分消掉分母,求导后带入1

    通分,分子分母同时干掉自己的分母

    A(x),C(x)都是知道的

    带入1

    前缀后缀积,

    前缀后缀求导dp,枚举当前的(1-vx)导不导

    或者发现带入1,1-x是0,可以直接对v=1特殊处理,别的含有(1-x)的连乘积都是0

    注意:

    多次进入calc

    初值时,滚动数组f[0]也要先清空

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=100+5;
    const int M=5e4+5;
    const int NM=5e6+5;
    const int mod=998244353;
    int n,s[N];
    int p[N];
    int ad(int x,int y){
        return (x+y)>=mod?x+y-mod:x+y;
    }
    void inc(int &x,int y){
        x=ad(x,y);
    }
    int mul(int x,int y){
        return (ll)x*y%mod;
    }
    int qm(int x,int y=mod-2){
        int ret=1;while(y){
            if(y&1) ret=mul(ret,x);x=mul(x,x);y>>=1;
        }return ret;
    }
    int f[2][2*M];
    struct po{
        int a,v;
    }t[2*M];
    int pre[2*M],bac[2*M];
    int Pr[2*M],Bc[2*M];
    int tot,iv,iv2;
    pair<int,int>calc(int *s){
        int tmp=0;
        memset(f[tmp],0,sizeof f[tmp]);
        f[tmp][0+tot]=1;
        for(reg i=1;i<=n;++i){
            tmp^=1;
            memset(f[tmp],0,sizeof f[tmp]);
            for(reg j=-tot;j<=tot;++j){
                if(f[tmp^1][j+tot]){
                    int lp=f[tmp^1][j+tot];
                    inc(f[tmp][j+tot+p[i]],mul(iv2,lp));
                    if(s[i]&1){
                        inc(f[tmp][j+tot-p[i]],mod-mul(iv2,lp));
                    }else{
                        inc(f[tmp][j+tot-p[i]],mul(iv2,lp));
                    }
                }
            }
        }
        for(reg i=-tot;i<=tot;++i){
            t[i+tot].a=f[tmp][i+tot];
            t[i+tot].v=mul(ad(mod,i),iv);
    
            // cout<<" i "<<i<<" a "<<t[i+tot].a<<" v "<<t[i+tot].v<<endl;
    
            if(i!=-tot) pre[i+tot]=mul(pre[i+tot-1],ad(1,mod-t[i+tot].v));
            else pre[i+tot]=ad(1,mod-t[i+tot].v);
            
            if(i!=-tot) Pr[i+tot]=ad(mul(Pr[i+tot-1],ad(1,mod-t[i+tot].v)),mul(pre[i+tot-1],mod-t[i+tot].v));
            else Pr[i+tot]=mod-t[i+tot].v;
        }
        for(reg i=tot;i>=-tot;--i){
            int v=t[i+tot].v;
            int now=i+tot;
            if(i!=tot) bac[now]=mul(bac[now+1],ad(1,mod-v));
            else bac[now]=ad(1,mod-v);
    
            if(i!=tot) Bc[now]=ad(mul(Bc[now+1],ad(1,mod-v)),mul(bac[now+1],mod-v));
            else Bc[now]=mod-v;
        }
        
        // prt(pre,0,tot+tot);
        // prt(bac,0,tot+tot);
    
        pii ret;ret.fi=ret.se=0;
        for(reg i=-tot;i<=tot;++i){
            int a=t[i+tot].a;
            int tmp=t[i+tot].a;
            if(i!=-tot) tmp=mul(tmp,pre[i+tot-1]);
            if(i!=tot) tmp=mul(tmp,bac[i+tot+1]);
            ret.fi=ad(ret.fi,tmp);
    
            tmp=0;
            int now=i+tot;
            if(i==-tot){
                tmp=mul(a,Bc[now+1]);
            }else if(i==tot){
                tmp=mul(a,Pr[now-1]);
            }else{
                tmp=ad(mul(mul(pre[now-1],a),Bc[now+1]),mul(mul(bac[now+1],a),Pr[now-1]));
            }
            ret.se=ad(ret.se,tmp);
        }
        // cout<<" ret "<<ret.fi<<" "<<ret.se<<endl;
        return ret;
    }
    int main(){
        rd(n);
        for(reg i=1;i<=n;++i) rd(s[i]);
        for(reg i=1;i<=n;++i) rd(p[i]),tot=ad(tot,p[i]);
        iv=qm(tot);
        iv2=qm(2); 
        
        pii A=calc(s);
        // cout<<endl<<endl;
       memset(s,0,sizeof s);
        pii C=calc(s);
        ll ans=mul(ad(mul(A.se,C.fi),mod-mul(A.fi,C.se)),qm(mul(C.fi,C.fi)));
        ot(ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
  • 相关阅读:
    css 三种布局定位
    居中布局注意的要点
    CSS盒子3D模型
    SpringMVC中JSP取不到ModelAndView的数据原因
    如何让 height:100%; 起作用
    css形变
    消除html元素之间空白
    h5移动端网页头部标签模板
    大数据之Hadoop核心之HDFS
    大数据之Hadoop集群搭建
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10865003.html
Copyright © 2011-2022 走看看