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
树的直径...