AGC007 C Pushing Balls

題意

參考:https://hk-cnyali.com/2018/02/07/AGC007-C-Pushing-Balls/
有N+1個洞,中間間隔擺着N個球,然後每次隨機選一個球,隨機讓它向左或右滾,直到他經過第一個未有球進入的洞,它就滾進去了,問期望的球滾動總長度。

一句話題意:有2*n+1個點,每次隨機選擇兩個當前相鄰的點刪去,ans加上他們的距離,問ans的期望
除此之外,還有一個重要的條件:初始每兩個相鄰點之間的距離是等差數列

題解

首先,有個很重要的,而且我不會證的性質:這樣操作一次後的期望序列仍然是相鄰點之間的距離是等差數列
(自己yy了一個證明,然而不太嚴謹:對於每一個點,設其到左邊距離爲x+zd,它關於左右的距離只會在三種情況下改變,一種是左邊沒了,那麼他到左邊的距離就變成了3x+(z+z-1+z-2)d,另一種是右邊沒了,那麼就是3x+(z+1+z+2+z+3)d,還有可能是自己沒了…所以似乎期望增量都是一樣的,所以就還是等差?)
知道了還是等差之後,我們就可以逐步向下迭代成子問題了
我們令m爲等差數列的項數(說白了就是n*2)
比如說,期望的滾動距離
ans+=2x+(m1)d2ans+=\frac{2x+(m-1)d}{2}
首項的期望稍微有些複雜
在這裏插入圖片描述
如果選中的是最左邊兩個,那麼首項就是x+2d
如果選的是第二三個,那麼首項就是3x+3d
其他的話,首項還是x
於是我們加起來,再除個m,有
x=(m+2)x+5dmx'=\frac{(m+2)*x+5*d}{m}
然後用期望的總和和期望的首項,我們就可以算出期望的公差爲
d=(m+4)dmd'=\frac{(m+4)d}{m}
然後我們就這樣依次迭代即可

以上。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	ll n;
	double x,d;
	scanf("%lld%lf%lf",&n,&x,&d);
	double ans=0;
	ll m=2*n;
	while(m){
		ans+=(2*x+(m-1)*d)*1.0/2;
        x=((m+2)*x+5*d)*1.0/m;
        d=(m+4)*d*1.0/m;
        m-=2;
	}
	printf("%.10f",ans);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章