• 51 nod 1628 非波那契树


    原题链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1628

    花了一个早上+半个下午终于把这题切掉了……

    (膜出题人)

    我们考虑斐波那契数列的通项公式:

    $$ F(i)=[(frac{1+sqrt{5}}{2})^{i}-(frac{1-sqrt{5}}{2})^{i}]*frac{1}{sqrt{5}} $$

    最后的$ frac{1}{sqrt{5}} $ 我们可以拿掉,输出时再丢进答案。

    然后考虑对前面两项分开单独处理。

    设$G(i)=(frac{1+sqrt{5}}{2})^{i}$ 那么这时可以发现 $G(a+b)=G(a)*G(b)$ 有了这个性质,我们就可以把东西统计完再乘起来了。

    具体来说,先预处理出从一个点向上走$2^{i}$步之后,这条链上的点从下往上走能得到的贡献,从上往下相同,以及该链内部的点两两之间对答案的贡献(其实前面从上往下的统计只是为这部分服务)。

    对于每组询问,先求出两点的lca,然后分别统计这两个点到lca的链的答案,再合并起来,合并的过程有很多细节,详见代码。

    运气#1(UPD at 2017.4.24:已经被踩辣)

    #include<cstdio>
    #include<algorithm>
    #define MN 100001
    using namespace std;
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    const int S1=691504013,S2=308495997,MOD=1e9+9,S3=276601605;
    struct na{int y,ne;}b[MN<<1];
    int n,m,x,y,f[MN][21],g[MN][21],G[MN][21],A[MN][21],K[MN][21],l[MN],num=0,S[2][MN],X[MN],Y[MN],Z[MN],s[MN],de[MN],mmh[MN],Lx[MN],Ly[MN],AP[MN];
    inline void in(int x,int y){b[++num].y=y;b[num].ne=l[x];l[x]=num;}
    inline int M(int x){while (x>=MOD)x-=MOD;while (x<0)x+=MOD;return x;}
    void DFS(int x){
        s[x]=1;
        register int i;
        for (i=1;i<=20;i++) if (f[f[x][i-1]][i-1]) f[x][i]=f[f[x][i-1]][i-1];else break;
        for (i=1;i<=20;i++) if (f[K[x][i-1]][i]) K[x][i]=f[K[x][i-1]][i];else break;
        for (;i;i--) K[x][i]=K[x][i-1];K[x][0]=x;
        for (i=l[x];i;i=b[i].ne)
        if (b[i].y!=f[x][0]){
            de[b[i].y]=de[K[b[i].y][0]=f[b[i].y][0]=x]+1;
            DFS(b[i].y);
            AP[x]=M(AP[x]+1LL*s[x]*s[b[i].y]%MOD);
            s[x]+=s[b[i].y];
        }
    }
    inline int lca(int x,int y,int &a,int &b){
        for (register int i=20;i>=0;i--)
        if (de[f[x][i]]>=de[y]) x=f[x][i];
        if (x==y) return x;
        for (register int i=20;i>=0;i--)
        if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        a=x;b=y;
        return f[x][0];
    }
    void dfs(int x,int o){
        A[x][0]=1LL*AP[x]*S[o][1]%MOD;
        g[x][0]=G[x][0]=1LL*s[x]*S[o][1]%MOD;
        for (register int i=1;i<=20;i++)
        if (K[x][i])
        g[x][i]=M((1LL*(g[x][i-1]-s[K[x][i-1]])*S[o][1<<(i-1)]+g[f[x][i-1]][i-1])%MOD),
        G[x][i]=M((1LL*(G[f[x][i-1]][i-1]-g[K[x][i-1]][0])*S[o][1<<(i-1)]+G[x][i-1])%MOD),
        A[x][i]=M((1LL*g[x][i-1]*(G[f[x][i-1]][i-1]-g[K[x][i-1]][0])+A[x][i-1]+A[f[x][i-1]][i-1]-1LL*s[K[x][i-1]]*M(G[f[x][i-1]][i-1]-g[K[x][i-1]][0]))%MOD);
        for (register int i=l[x];i;i=b[i].ne)
        if (b[i].y!=f[x][0]) dfs(b[i].y,o);
    }
    inline void work(int x,int z,int &_A,int &_g,int o){
        int p=0;_A=0;_g=0;
        for (register int i=20;i>=0;i--)
        if (de[K[x][i]]>=de[z]){
            _A=M((1LL*_g*(G[x][i]-g[p][0])+_A+A[x][i]-1LL*s[p]*M(G[x][i]-g[p][0]))%MOD);
            _g=M((1LL*(_g-s[p])*S[o][1<<i]+g[x][i])%MOD);
            if (K[x][i]==z) return;
            p=K[x][i];
            x=f[x][i];
        }
    }
    inline void calc(int x){
        int Ax,Ay,gx,gy;
        register int i;
        dfs(1,x);
        for (i=1;i<=m;i++)
        if (Y[i]==Z[i]){
            work(X[i],Z[i],Ax,gx,x);
            mmh[i]=M(mmh[i]+(x?-1LL:1LL)*(1LL*gx*(n-s[Z[i]])+Ax)%MOD);
        }else{
            work(X[i],Lx[i],Ax,gx,x);work(Y[i],Ly[i],Ay,gy,x);
            mmh[i]=M(mmh[i]+(x?-1LL:1LL)*(1LL*(gx+gy)*(n-s[Lx[i]]-s[Ly[i]])%MOD*S[x][1]+1LL*gx*gy%MOD*S[x][1]+Ax+Ay+A[Z[i]][0]-(1LL*s[Lx[i]]*(s[Z[i]]-s[Lx[i]])+1LL*s[Ly[i]]*(s[Z[i]]-s[Lx[i]]-s[Ly[i]]))%MOD*S[x][1]+(1LL*(s[Z[i]]-s[Lx[i]]-s[Ly[i]])*(n-s[Z[i]]))%MOD*S[x][1])%MOD);
        }
    }
    int main(){
        register int i;
        n=read();
        for (i=1;i<n;i++) x=read(),y=read(),in(x,y),in(y,x);
        S[0][0]=S[1][0]=1;
        for (i=1;i<=n;i++) S[0][i]=1LL*S[0][i-1]*S1%MOD,S[1][i]=1LL*S[1][i-1]*S2%MOD;
        de[1]=1;DFS(1);
        m=read();
        for (i=1;i<=m;i++){
            X[i]=read();Y[i]=read();
            if (de[X[i]]<de[Y[i]]) swap(X[i],Y[i]);
            Z[i]=lca(X[i],Y[i],Lx[i],Ly[i]);
        }
        calc(0);calc(1);
        for (i=1;i<=m;i++) printf("%d
    ",1LL*mmh[i]*S3%MOD);
    }
    View Code
  • 相关阅读:
    Git 一些关于 Git、Github 的学习资源
    迁移应用数据库到MySQL Database on Azure
    释放虚拟磁盘未使用空间来减少计费容量
    链路层的双链路--大型服务器的优化体系
    解读 Windows Azure 存储服务的账单 – 带宽、事务数量,以及容量
    产品技术恩仇记:这个需求真的很简单吗?
    语音识别真的比肩人类了?听听阿里iDST初敏怎么说
    《伟大的计算原理》一云计算
    如何在 CentOS 7 用 cPanel 配置 Nginx 反向代理
    安装PHP的memcache扩展
  • 原文地址:https://www.cnblogs.com/Enceladus/p/5761384.html
Copyright © 2020-2023  润新知