洛谷 P4581 - [BJOI2014]想法(随机化)
奇怪的随机化题,知道题解不长但是还是写一写,以免我忘了这个 trick。
考虑随机给每道题目一个 \([0,V]\) 的权值,然后求出每个点能够到达的点权值的最小值,多次随机取平均值,根据概率论,假设点 \(x\) 的答案为 \(ans_x\),那么这个权值的期望值应当为 \(\dfrac{V}{ans_x+1}\)。
根据我们求得的平均权值得到 \(ans\) 即可。
const int MAXN=1e6;
const int V=1e9;
mt19937 rng(time(0));
int n,m,mn[MAXN+5],x[MAXN+5],y[MAXN+5],c;double res[MAXN+5];
int main(){
scanf("%d%d",&n,&m);
for(int i=m+1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
while(clock()<1.9*CLOCKS_PER_SEC){
for(int i=1;i<=m;i++)mn[i]=rng()%V+1;
// for(int i=1;i<=m;i++)printf("%d%c",mn[i]," \n"[i==m]);
for(int i=m+1;i<=n;i++)mn[i]=min(mn[x[i]],mn[y[i]]);
for(int i=m+1;i<=n;i++)res[i]+=mn[i];
c++;
}
for(int i=m+1;i<=n;i++)printf("%d\n",(int)round(V/(res[i]/c)-1));
return 0;
}