1. 程式人生 > >【2018/10/17測試T1】發電機

【2018/10/17測試T1】發電機

【題目】

內網傳送門
外網傳送門

【分析】

不是第一次接觸期望了,但之前一直不懂,今天聽課後感覺多多少少有點收穫,就記一下

定義:試驗中每次可能結果的概率乘以其結果的總和

一個經典的例子就是擲骰子,每個點數的概率都是 1 6 \frac{1}{6} ,那期望就是 1

6 ( 1 + 2 + 3 + 4
+ 5 + 6 ) = 3.5 \frac{1}{6}*(1+2+3+4+5+6)=3.5

一個關於期望的重要性質:線性性,即 E ( X + Y ) = E ( X ) + E ( Y ) E(X+Y)=E(X)+E(Y)

然後讓我們回到這道題吧

可以發現在 i i 點放置發電機的概率是 1 s i z e i \frac{1}{size_i} ,其中 s i z e i size_i i i 的子樹的大小

由於期望的線性性,統計出每個點的 s i z e size ,然後用逆元求解然後求和即可

逆元用快速冪求的話要多套一個 l o g log ,因此不能用快速冪,要用線推

【程式碼】

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10000005
#define Mod 998244353
using namespace std;
int Read()
{
	int x=0;char c=getchar();
	while(!isdigit(c))  c=getchar();
	while(isdigit(c))  {x=(x<<1)+(x<<3)+(c^'0');c=getchar();}
	return x;
}
int inv[N],size[N],father[N];
int main()
{
//	freopen("f.in","r",stdin);
//	freopen("f.out","w",stdout);
	int n,i,ans=0;
	n=Read();
	//scanf("%d",&n);
	inv[1]=1;
	for(i=2;i<=n;++i)
	{
		father[i]=Read();
		//scanf("%d",&father[i]);
		inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod;
	}
	for(i=n;i>=1;--i)
	{
		size[i]++;
		size[father[i]]+=size[i];
		ans=(ans+inv[size[i]])%Mod;
	}
	printf("%d",ans);
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}