题解 | #和的期望#

和的期望

https://ac.nowcoder.com/acm/contest/71320/A

A
数学
对于选择k个,期望可以写作∑(ai+..ak)/(n..n-k+1),对于分子的求和,考虑每个元素的出现次数,在所有的情况中,乘法定理可以说明ai共出现了k(n-1..n-k+1)次,与分母约简后,可以化简为 k/n∑ai,对于除法,使用费马小定理保证,a/bmodp=a*b^mod-2,次方利用快速幂进行计算。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define maxx 310000
#define mod 998244353
#define int long long
int all[maxx];
int v,e,k,a,b,n,m,t,x,y,l,r,neww,neww1,w,ans,x1,x2;
int sum;
int poww(int i,int j)
{
  if(j==0) return 1;
  if(j==1) return i%mod;
  int q=poww(i,j/2);
  if(j%2==0) return (q*q)%mod;
  else return ((q*q)%mod*i%mod)%mod;
}

signed main()
{
  cin>>n;
  for(int i=1;i<=n;++i)
  {
    cin>>all[i];
    sum=(sum+all[i])%mod;
  }
  for(int i=1;i<=n;++i)
  cout<<((i%mod*sum%mod)%mod*poww(n,mod-2))%mod<<" ";

  
}
B
动态规划
约定0为A,1是B。
dp[i][j]表示已被(j+1)%2捡走了当前位置的,到树根的最大/小值(0/1),dp1[i][j]表示以i的子孙为根的dp[i][j]的最小/最大值,后者用于前者的转移。
然后依照题目所述进行转移,其中到子孙的每一个位置直接使用dp1[i][(j+1)%2]一步代替,转移顺序可以由深到浅,深度可以dfs计算。
输出dp[1][0]
#include<bits/stdc++.h>
using namespace std;
#define INF 1e20
#define maxx 310000
#define mod 998244353
#define int long long
int dp[maxx][2];
int dp1[maxx][2];
int val[maxx];
int fa[maxx];

int v,e,k,a,b,n,m,t,x,y,l,r,neww,neww1,w,ans,x1,x2;
int sum,mxc;
vector<int> G[maxx];
vector<int> ceng[maxx];
void dfs(int i,int cg)
{
  ceng[cg].push_back(i);
  mxc=max(mxc,cg);
  for(int j=0;j<G[i].size();++j)
  dfs(G[i][j],cg+1);
}
void solve()
{
   

   for(int i=mxc;i>=1;--i)
   for(int j=0;j<ceng[i].size();++j)
    {
       int x=ceng[i][j];
       dp[x][0]=dp1[x][0]=INF;
       dp[x][1]=dp1[x][1]=-INF;
    }  

  for(int i=mxc;i>=1;--i)
    for(int j=0;j<ceng[i].size();++j)
      {int x=ceng[i][j];
      for(int k=0;k<G[x].size();++k)
      {dp[x][0]=min(dp[G[x][k]][0],dp[x][0]);
      dp[x][1]=max(dp[G[x][k]][1],dp[x][1]);
      }
      if(G[x].size()==0)
      {
       dp[x][0]=dp1[x][0]=-val[x];
       dp[x][1]=dp1[x][1]=val[x];
       continue;
      }     
      dp1[x][0]=dp[x][1]-val[x];
      dp1[x][1]=dp[x][0]+val[x];
      dp[x][0]=min(dp1[x][0],dp[x][0]);
      dp[x][1]=max(dp1[x][1],dp[x][1]);
     }
  
}

signed main()
{
  cin>>t;
  for(int i=1;i<=t;++i)
  {
    cin>>n;
    for(int i=2;i<=n;++i) cin>>val[i];
    for(int i=2;i<=n;++i) 
    {cin>>fa[i];
     G[fa[i]].push_back(i);
    }
    dfs(1,1);
    solve();

    cout<<dp1[1][0]<<"\n";
   
   for(int i=1;i<=mxc;++i)
    ceng[i].clear();
    for(int i=1;i<=n;++i)
    G[i].clear();
  

  }
 
  
}

C
树的直径...


全部评论

相关推荐

07-25 11:26
清华大学 Java
打开电脑,思绪又回到了7月份刚开始的时候,感觉这个月过的如梦如幻,发生了太多事,也算是丰富了我本就是平淡的人生吧太早独立的我习惯了一切都是自己做决定,拥有绝对的决定权,而且永远不会听取别人的建议。我就是那个恋爱四年出轨的男主啦,感觉既然在牛客开了这个头,那我就要做个有始有终的人。从我出轨到结束再到和女朋友和好如初真的太像一场梦了,短短的一个月我经历了太多,也成长了很多,放下了那些本就不属于我的,找回了那些我不该放弃的。我的人生丰富且多彩,但人不能一直顺,上天总会让你的生活中出点乱子,有好有坏,让你学会一些东西,让你有成长。我和女朋友的恋爱四年太过于平淡,日常除了会制造一些小浪漫之外,我们的生活...
段哥亡命职场:不得不说,我是理解你的,你能发出来足见你是个坦诚的人,至少敢于直面自己的内心和过往的过错。 这个世界没有想象中那样非黑即白,无论是农村还是城市,在看不见的阴影里,多的是这样的事。 更多的人选择站在制高点去谩骂,一方面是社会的道德是需要制高点的,另一方面,很多人不经他人苦,却劝他人善。 大部分的我们,连自己生命的意义尚且不能明晰,道德、法律、困境,众多因果交织,人会迷失在其中,只有真的走出来之后才能看明白,可是没走出来的时候呢?谁又能保证自己能走的好,走的对呢? 可是这种问题有些人是遇不到的,不去追寻,不去探寻,也就没了这些烦恼,我总说人生的意义在过程里,没了目标也就没了过程。 限于篇幅,没法完全言明,总之,这世界是个巨大的草台班子,没什么过不去了,勇敢面对,革故鼎新才是正确,祝你早日走出来。查看图片
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务