zoukankan      html  css  js  c++  java
  • CodeForces 543D:Road Improvement

    题目:http://codeforces.com/problemset/problem/543/D

    题意:给你一棵树,一开始边都是0,可以使任意的边变成1,对于每一个根节点求使得它到其他任一点的路径上只有一条0边的方案数。

    假设只求一个根,f[u]=∏(s[v]+1)

    然后移动根节点这样就可以通过遍历一遍树得到所有点的答案了。

    s[v]=(s[u]/(s[v]+1)+1)*s[v] 这样当前根和根的其他子树就变成v的子树了(前面那坨就是它的贡献。。

    (看起来是这样没错。。但是不能求逆元。因为s[u]可能为0 。。所以维护前缀和后缀bfs一遍就好了。。

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<map>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define maxn 200500
    #define maxk 69
    #define inf 0x7fffffff
    #define ll long long
    #define mm 1000000007
    using namespace std;
    struct data{int obj,pre;
    }e[maxn*2];
    ll g[maxn],s[maxn],ans[maxn],pr[maxn],sc[maxn];
    int head[maxn],a[maxn],vis[maxn],n,tot;
    int read(){
        ll x=0,f=1; char ch=getchar();
        while (!isdigit(ch)){if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    void insert(int x,int y){
        e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot;
    }
    ll ni(ll x){
        ll y=mm-2,ans=1;
        while (y){
            if (y&1) ans=ans*x%mm;
            x=x*x%mm;
            y>>=1;
        }
        return ans;
    }
    ll dfs(int u,int f){
        s[u]=1;
        for (int j=head[u];j;j=e[j].pre){
            int v=e[j].obj;
            if (v==f) continue;
            s[u]=s[u]*(dfs(v,u)+1LL)%mm;        
        }
        return s[u];
    }
    void go(){
        g[1]=1;
        queue<int> q; clr(vis,0); q.push(1);
        while (!q.empty()){
            int u=q.front(); q.pop(); vis[u]=1;
            int sum=0;
            for (int j=head[u];j;j=e[j].pre){
                int v=e[j].obj;
                if (!vis[v]) a[++sum]=v; 
            }
            sort(a+1,a+1+sum);
            pr[0]=1; rep(i,1,sum) pr[i]=pr[i-1]*(s[a[i]]+1)%mm;
            sc[sum+1]=g[u]; down(i,sum,1) sc[i]=sc[i+1]*(s[a[i]]+1)%mm;
            rep(i,1,sum) {
                s[a[i]]=(pr[i-1]*sc[i+1]%mm+1)%mm*s[a[i]]%mm;
                g[a[i]]=(pr[i-1]*sc[i+1]%mm+1)%mm;
                q.push(a[i]); 
            }
        }
    }
    int main(){
        n=read();
        rep(i,2,n) {
            int x=read(); insert(x,i); insert(i,x);
        }
        dfs(1,0);
        go();
        rep(i,1,n-1) printf("%lld ",s[i]%mm); printf("%lld
    ",s[n]%mm);
        return 0;
    }
  • 相关阅读:
    js如何求一组数中的极值
    五星评分效果 原生js
    省市区三级联动
    jq表头固定
    css垂直居中 两种方法
    node.js grunt文件压缩
    js 定时器
    动态规划---最长公共子序列
    AES,RSA对称加密和非对称加密
    正则表达式学习笔记
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5186596.html
Copyright © 2011-2022 走看看