• 西行妖下


    西行妖下
    给一棵树,每个点有一个权值,解封概率为f[i]/i!,fi为长度为i的排列错排方案数,问某路径解封点数期望。支持修改(+,*)

    原权值为1,修改为正整数,答案保留1位小数

    nq 8e4


    solution

    错排公式:f[i]=(n-1)*(f[i-1]+f[i-2])

    证明:考虑最后一个元素,它有n-1种合法位置,然后如果那个位置的数在i即为f[n-2],不在i即为f[n-1]

    首先我们打出错排方案的比值,发现它似乎是收敛的

    也就是i>10时 F[i]/i! 基本不变

    于是我想到了--上帝造题七分钟2!!

    如果权值>20就当成20,对最终影响不变了

    如果修改次数小于20则暴力修改,否则不管他

    不过这个奇怪的题似乎要留20位才不会被卡精,照理说10位够了

    10位=20分。。。。。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define db double
    #define maxn 80005
    using namespace std;
    int n,q,head[maxn],top[maxn],size[maxn],fa[maxn],dfn[maxn],dy[maxn],deep[maxn],son[maxn];
    int t1,t2,a,b,tot,sc,li,ri,val;
    char ch[10];
    struct node{
        int v,nex;
    }e[maxn*2];
    struct no{
        int l,r,fl,x;
        double v;
    }tree[maxn*8];
    db Val[21]={
    0.00000000000000000000,
    0.00000000000000000000,
    0.50000000000000000000,
    0.33333333333333331000,
    0.37500000000000000000,
    0.36666666666666664000,
    0.36805555555555558000,
    0.36785714285714288000,
    0.36788194444444444000,
    0.36787918871252206000,
    0.36787946428571427000,
    0.36787943923360589000,
    0.36787944132128159000,
    0.36787944116069116000,
    0.36787944117216193000,
    0.36787944117139720000,
    0.36787944117144500000,
    0.36787944117144217000,
    0.36787944117144233000,
    0.36787944117144233000,
    0.36787944117144233000,
    };
    void lj(int t1,int t2){
        e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
    }
    void dfs1(int k,int fath){
        fa[k]=fath;deep[k]=deep[fath]+1;
        int sz=0,gp=-1;
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v==fath)continue;
            top[e[i].v]=e[i].v;
            dfs1(e[i].v,k);sz+=size[e[i].v];
            if(gp==-1||size[e[i].v]>size[gp])gp=e[i].v;
        }
        size[k]=sz+1;son[k]=gp;
    }
    void dfs2(int k){
        dfn[k]=++sc;dy[sc]=k;
        if(son[k]!=-1){
            top[son[k]]=top[k];dfs2(son[k]);
        }
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v==fa[k]||e[i].v==son[k])continue;
            dfs2(e[i].v);
        }
    }
    void wh(int k){
        tree[k].v=tree[k*2].v+tree[k*2+1].v;
        tree[k].x=tree[k*2].x+tree[k*2+1].x;//not true
        tree[k].fl=(tree[k*2].fl&tree[k*2+1].fl);
    }
    void build(int k,int L,int R){
        tree[k].l=L;tree[k].r=R;
        if(L==R){
            tree[k].x=1;tree[k].v=0;return;
        }
        int mid=L+R>>1;
        build(k*2,L,mid);build(k*2+1,mid+1,R);
        wh(k);
    }
    void Add(int k){
        if(tree[k].fl)return;
        if(tree[k].l==tree[k].r){
            tree[k].x+=val;
            if(tree[k].x>=20)tree[k].x=20,tree[k].fl=1;
            tree[k].v=Val[tree[k].x];
            return;
        }
        int mid=tree[k].l+tree[k].r>>1;
        if(li<=mid)Add(k*2);if(ri>mid)Add(k*2+1);
        wh(k);
    }
    void Mu(int k){
        if(tree[k].fl)return;
        if(tree[k].l==tree[k].r){
            tree[k].x*=val;
            if(tree[k].x>=20)tree[k].x=20,tree[k].fl=1;
            tree[k].v=Val[tree[k].x];
            return;
        }
        int mid=tree[k].l+tree[k].r>>1;
        if(li<=mid)Mu(k*2);if(ri>mid)Mu(k*2+1);
        wh(k);
    }
    db Q(int k){
        if(tree[k].l>=li&&tree[k].r<=ri){
            return tree[k].v;
        }
        int mid=(tree[k].l+tree[k].r)>>1;
        db tmp=0;
        if(li<=mid)tmp+=Q(k*2);if(ri>mid)tmp+=Q(k*2+1);
        return tmp;
    }
    int main()
    {
        cin>>n;
        for(int i=1;i<n;i++){
            scanf("%d%d",&t1,&t2);
            lj(t1,t2);lj(t2,t1);    
        }
        dfs1(1,0);top[1]=1;dfs2(1);
        build(1,1,sc);
        cin>>q;
        for(int i=1;i<=q;i++){
            scanf(" %s",ch);
            if(ch[0]=='A'){
                scanf("%d%d%d",&a,&b,&val);
                t1=top[a],t2=top[b];
                while(t1!=t2){
                    if(deep[t1]<deep[t2])swap(t1,t2),swap(a,b);
                    li=dfn[t1],ri=dfn[a];
                    Add(1);
                    a=fa[t1];t1=top[a];
                }
                if(deep[a]<deep[b])swap(a,b);
                li=dfn[b],ri=dfn[a];
                Add(1);
            }
            if(ch[0]=='M'){
                scanf("%d%d%d",&a,&b,&val);
                if(val==1)continue;
                t1=top[a],t2=top[b];
                while(t1!=t2){
                    if(deep[t1]<deep[t2])swap(t1,t2),swap(a,b);
                    li=dfn[t1],ri=dfn[a];
                    Mu(1);
                    a=fa[t1];t1=top[a];
                }
                if(deep[a]<deep[b])swap(a,b);
                li=dfn[b],ri=dfn[a];
                Mu(1);
            }
            if(ch[0]=='Q'){
                scanf("%d%d",&a,&b);
                t1=top[a],t2=top[b];
                db ans=0;
                while(t1!=t2){
                    if(deep[t1]<deep[t2])swap(t1,t2),swap(a,b);
                    li=dfn[t1],ri=dfn[a];
                    ans+=Q(1);
                    a=fa[t1];t1=top[a];
                }
                if(deep[a]<deep[b])swap(a,b);
                li=dfn[b],ri=dfn[a];
                ans+=Q(1);
                printf("%.1lf
    ",ans);
            }
        }
        return 0;
    }
     


     

  • 相关阅读:
    HTML实现“摇一摇”效果,比较好的两篇文章;
    mongodb查询关于大于小于的用法;
    thenjs的应用
    js原生forEach、map与jquery的each、$.each的区别
    nodejs的url模块中的resolve()的用法总结
    2021.1.22 刷题(环形链表)
    2021.1.21 刷题(定义链表)
    2021.1.21 刷题(移除链表元素)
    2021.1.20 刷题(螺旋矩阵)
    滑动窗口-长度最小的子数组
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358786.html
Copyright © 2020-2023  润新知