【NOIP2017提高A组冲刺11.2】救赎(数学期望)

来源:互联网 发布:网络电视缴费 编辑:程序博客网 时间:2024/06/05 23:48

Description

“是的。”我回答,“我不会忘记你。在森林里我会一点点记起往日的世界。要记起的大概很多很多:各种人、各种场所、各种光、各种歌曲……”
——村上春树《世界尽头与冷酷仙境》

在没有心存在的世界尽头,音乐能够使小镇居民消散的心重新聚拢成形。作为镇子里唯一一个还残留着些许音乐记忆的人,我逐渐记起了往昔点滴……

记忆中有一棵无根树,有n个节点。
对于一棵有根树的每一个非叶子节点,我们都等概率选中其一个儿子节点作为偏好儿子。对于一条从父亲指向儿子的树边(u,v),如果v是u的偏好儿子,则称这条边为重边,否则为轻边。
我们定义一棵有根树的权值为其每一个节点到根路径上的轻边条数的和的期望值。
请对无根树每一个节点输出其为根的有根树的权值。答案模998244353。

Input

文件第一行是一个正整数n。
接下来n-1行,每行两个正整数(x,y)表示一条树边。

Output

输出文件共n行,每一行一个整数表示答案。

Sample Input

5
1 2
1 3
3 4
3 5

Sample Output

3
1
665496238
499122178
499122178

Data Constraint

对于10%的数据,保证n<=10。
对于30%的数据,保证n<=2000。
对于100%的数据,保证n<=10^5。

题解

这个题的实现和天天爱跑步有的一拼。 - - - - 一位大佬在赛后如此说道。
首先,我们通过思考,可以想出来O(n2)的做法。
dpi=nj=1sizejPedge(on the path of i->j)
然后我们来思考如何优化。
我们考虑枚举每条边,计算贡献。
我们发现,一条边对一个点的贡献只有两种值,分别对应这个点在这条边的两侧。
所以,我们在用上面的方程计算出贡献之后,我们只需要分别将两边的点加上贡献即可。
我们可以发现,这两类点,一类其实就是那条边的子树内的所有点,另一类就是其他点。
所以我们只需要随便选一个点进行一遍dfs,得到所需信息,以及dfs序,就可以做了。
修改时差分地在dfs序上修改即可。
然后发现这样做都过不了样例,重新手玩样例之后,发现其实有两个点是特殊的,就是边的两个端点。
它们的值还要另外计算。
这个题其实就是不好调试。
代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<cstdlib>#define ll long longusing namespace std;inline int read(){    int x=0;char ch=' ';int f=1;    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();    if(ch=='-')f=-1,ch=getchar();    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();    return x*f;}const int N=1e5+5;const int p=998244353;struct edge{int to,next;}e[N<<1];int n,tot;int head[N],dfn_clock,mp[N];ll inv[N],ans[N],all,du[N],size[N];inline void addedge(int x,int y){e[++tot].to=y;e[tot].next=head[x];head[x]=tot;}inline ll frac(int x,int y){return (x*inv[y])%p;}inline void getinv(){    inv[0]=inv[1]=1;    for(int i=2;i<=n;i++)inv[i]=((p-p/i)*inv[p%i])%p;}inline void dfs(int x,int fa){    size[x]=1;mp[x]=++dfn_clock;    for(int i=head[x];i;i=e[i].next){        int u=e[i].to;        if(u==fa)continue;        dfs(u,x);        size[x]+=size[u];    }}inline void dfs2(int x,int fa){    for(int i=head[x];i;i=e[i].next){        int u=e[i].to;        if(u==fa)continue;        ll sizeu=size[u],dux=du[x],duu=du[u],mpx=mp[x],mpu=mp[u];        ll num=(sizeu*frac(max(dux-2,0LL),dux-1))%p;        all+=num;if(all>p)all%=p;        ans[mpu]-=num;        ans[mpu+sizeu]+=num;        ans[mpx]-=num;        ans[mpx+1]+=num;        num=(sizeu*frac(dux-1,dux))%p;        ans[mpx]+=num;        ans[mpx+1]-=num;        num=((n-sizeu)*frac(max(duu-2,0LL),duu-1))%p;        ans[mpu]+=num;        ans[mpu+sizeu]-=num;        ans[mpu]-=num;        ans[mpu+1]+=num;        num=((n-sizeu)*frac(duu-1,duu))%p;        ans[mpu]+=num;        ans[mpu+1]-=num;        dfs2(u,x);    }}int main(){    freopen("redemption.in","r",stdin);    freopen("redemption.out","w",stdout);    n=read();    getinv();    for(int i=1;i<n;i++){        int x=read(),y=read();        addedge(x,y);addedge(y,x);        du[x]++;du[y]++;    }    dfs(1,0);    dfs2(1,0);    ans[0]=all;    for(int i=1;i<=n;i++){        ans[i]=(ans[i-1]+ans[i])%p;    }    for(int i=1;i<=n;i++){        printf("%lld\n",(ans[mp[i]]+p)%p);    }    return 0;}
阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 灵异附身夫妻不合怎么办 鞋子买大了半码怎么办 鞋子买小了半码怎么办 黑布鞋鞋面白了怎么办 黑布鞋不黑了怎么办 黑布鞋退白了怎么办 老北京布鞋款式太少怎么办 老人输液抽搐后昏迷怎么办 头七家里有狗怎么办 股票退市股民的钱怎么办 美国股票退市股民怎么办 百度云字幕和视频不同步怎么办 百度云加载字幕有延迟怎么办 很难适应新环境怎么办 蜘蛛丝碰到嘴唇上起包有毒怎么办? 电瓶车在路上爆胎了怎么办 嘴被虫子咬肿了怎么办 高铁管家购票失败怎么办 高铁车厢空调冷怎么办 高铁票过了时间怎么办 网购火车票丢了怎么办 改签没有票了怎么办 火车票取了没赶上车怎么办 上车后车票丢了怎么办 晒了吗任务过期怎么办 坐火车买了站票怎么办 坐火车忘记带票怎么办 距离二本线差几分怎么办 行李包落火车候车厅怎么办 高铁票买错地点怎么办 高铁票买错日期怎么办 票买错时间了怎么办 上高铁了票丢了怎么办 上车前高铁票丢了怎么办 高铁安检没收的东西怎么办 高铁安检员老了怎么办 高铁安检喷雾拍照了怎么办 十个小时的高铁怎么办 华为开机需要激活码怎么办 高铁提前上车了出站怎么办 买火车票忘记带身份证怎么办