其实原来看到这题是真的不想做的 毕竟真的特别怕期望题
后来莫名发现自己打了正解 也是很震惊的2333
Description
对于一棵树,每次随机染黑一个叶子(可能会重复染黑),期望多少次后直径变小
Solution
第一种R为偶数的情况时:找一个点root,所有的直径都经过这个root点,以此点为根
dpx=R/2的点可能是直径断点,先统计出来个数(x1),把所有dpx=R/2的点按他是root的哪一棵子树分成几个集合
直径改变了,当且仅当只剩下一个集合的点没有被删完。
第二种R为奇数的情况时:
把必经边分成两个集合,集合中的点为dpx=R/2(向下取整)把x1也一样的统计,就成了跟上述情况类似了
无关点可当做一开始就被删掉了,所以再删掉一个没被删的点的代价就是全部叶子数/还剩的点的个数
问题转化成:每删除一个剩下的点,求删剩一个集合的期望值
1 #include <bits/stdc++.h> 2 #define N 500010 3 #define Mo 998244353 4 using namespace std; 5 long long n,m,ans,jc[N],jcn[N],sum[N]; 6 long long edge[N*2][2],e1[N]; 7 long long a[N],f[N],t; 8 long long X,maxx,X1,d[N],x1,cnt; 9 inline long long ksm(long long b,long long p); 10 inline void init(){ 11 for (register long long i=1;i<=n;++i) 12 jc[i]=jc[i-1]*(long long)i%Mo; 13 jcn[n]=ksm(jc[n],Mo-2); 14 for (register long long i=n-1;i>=0;--i) 15 jcn[i]=jcn[i+1]*(i+1LL)%Mo; 16 } 17 inline long long read(){ 18 char ch=' ';long long x=0,y=1; 19 for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar()); 20 if(ch=='-')y=-1,ch=getchar(); 21 for(;ch>='0' && ch<='9';ch=getchar())x=x*10+ch-48; 22 x=x*y; 23 return x; 24 } 25 inline void Build(long long x,long long y){ 26 ++a[x];++a[y]; 27 edge[++cnt][0]=e1[x]; 28 edge[cnt][1]=y; 29 e1[x]=cnt; 30 edge[++cnt][0]=e1[y]; 31 edge[cnt][1]=x; 32 e1[y]=cnt; 33 } 34 inline long long ksm(long long b,long long p){ 35 long long a=b,c=p,ans=1; 36 while(p>0){ 37 if(p-p/2*2!=0) ans=(ans*b)%Mo; 38 b=(b*b)%Mo,p=p>>1; 39 } 40 return ans; 41 } 42 inline long long calc(long long m,long long n){return jc[m]*jcn[m-n]%Mo*jcn[n]%Mo;} 43 void dfs(long long x,long long s,long long father){ 44 long long max1=0,t=0,g; 45 for(register long long i=e1[x];i;i=edge[i][0]) 46 if(edge[i][1]!=father&&f[edge[i][1]]+1>s) 47 t=s,s=f[edge[i][1]]+1,max1=edge[i][1]; 48 else if(edge[i][1]!=father&&f[edge[i][1]]+1>t) 49 t=f[edge[i][1]]+1; 50 if (s+t>ans) ans=s+t; 51 if (maxx>=s){ 52 if (maxx>s) X=x; else X1=x; 53 maxx=s; 54 } 55 for(register long long i=e1[x];i;i=edge[i][0]) 56 if(edge[i][1]!=father){ 57 if (max1==edge[i][1]) 58 g=t+1; 59 else g=s+1; 60 dfs(edge[i][1],g,x); 61 } 62 } 63 long long dfs1(long long x,long long y,long long father){ 64 long long ans=(!y); 65 for(long long i=e1[x];i;i=edge[i][0]) 66 if(edge[i][1]!=father) 67 ans+=dfs1(edge[i][1],y-1,x); 68 return ans; 69 } 70 void dfs2(long long x,long long father){ 71 f[x]=0; 72 for(long long i=e1[x];i;i=edge[i][0]) 73 if(edge[i][1]!=father) 74 dfs2(edge[i][1],x),f[x]=max(f[x],f[edge[i][1]]+1); 75 x1+=(a[x]==1?1:0); 76 } 77 inline long long answer(long long m,long long m1){ 78 long long ans=0,ans1=0,t=0; 79 for (int i=m;i>=0;i--) 80 sum[i]=(sum[i+1]+m1*ksm(i,Mo-2))%Mo; 81 for (int j=1;j<=d[0];++j) 82 for (int i=0;i<=d[j]-1;++i){ 83 ans=(ans+(calc(d[j],i)*jc[m-d[j]+i-1]%Mo*(m-d[j])%Mo)*sum[d[j]-i+1]%Mo*jc[d[j]-i])%Mo; 84 ans1=(ans1+(calc(d[j],i)*jc[m-d[j]+i-1]%Mo*(m-d[j])%Mo))%Mo; 85 } 86 return ans*jcn[m]%Mo; 87 } 88 int main(){ 89 n=read(),jc[0]=1,maxx=1e9,t=0; 90 for (register long long i=1;i<=n-1;++i) 91 Build(read(),read()); 92 init(); 93 dfs2(1,0); 94 dfs(1,0,0); 95 if (ans&1){ 96 d[0]=2;d[1]=dfs1(X,ans/2,X1);d[2]=dfs1(X1,ans/2,X); 97 printf("%lld ",answer(d[1]+d[2],x1)); 98 } 99 else{ 100 for(register long long i=e1[X];i;i=edge[i][0]) 101 t+=(d[++d[0]]=dfs1(edge[i][1],ans/2-1,X)); 102 printf("%lld ",answer(t,x1)); 103 } 104 return 0; 105 }