https://vjudge.net/problem/AtCoder-agc007_c
题意:
给2n+1个物体,奇数位置为洞,偶数位置为球。
D
i
s
(
i
,
i
+
1
)
=
d
+
(
i
−
1
)
x
Dis(i,i+1)=d+(i-1)x
Dis(i,i+1)=d+(i−1)x。
现在任意选择一个求往左或右推。会掉到洞里面,其它球就会踩着他滚过去。
问最后所有球滚动的距离之和的期望。
解析:
题目转化为选择任意两个相邻的点,之后删除这两个点。
初始为 d , d + x , d + 2 x , d + 3 x , d + 4 x . . . d,d+x,d+2x,d+3x,d+4x... d,d+x,d+2x,d+3x,d+4x...,总共2n段
第一次选择获得期望长度为 S ( 2 n ) / 2 n S(2n)/2n S(2n)/2n
我们分析第一次滚动后形成的期望局面(每一段的)
- 选择点 ( 1 , 2 ) (1,2) (1,2)变为 d + 2 x , d + 3 x , d + 4 x . . . d+2x,d+3x,d+4x... d+2x,d+3x,d+4x...
- 选择点 ( 2 , 3 ) (2,3) (2,3)变为 3 d + 3 x , d + 3 d , d + 4 x . . . 3d+3x,d+3d,d+4x... 3d+3x,d+3d,d+4x...
- 选择点 ( 3 , 4 ) (3,4) (3,4)变为 d , d + 6 x , d + 4 x . . . d,d+6x,d+4x... d,d+6x,d+4x...
- 选择点 ( 4 , 5 ) (4,5) (4,5)变为 d , d + x , d + 9 x . . . d,d+x,d+9x... d,d+x,d+9x...
第一个段的期望:
- 有 1 2 n \dfrac{1}{2n} 2n1的概率变为 d + 2 x d+2x d+2x
- 有 1 2 n \dfrac{1}{2n} 2n1的概率变为 3 d + 3 x 3d+3x 3d+3x
- 有 2 n − 2 2 n \dfrac{2n-2}{2n} 2n2n−2的概率变为 d d d
- 所以期望为: 4 d + 5 x + ( 2 n − 2 ) d 2 n \dfrac{4d+5x+(2n-2)d}{2n} 2n4d+5x+(2n−2)d
第二个段的期望:
- 有 2 2 n \dfrac{2}{2n} 2n2的概率变为 d + 3 x d+3x d+3x
- 有 1 2 n \dfrac{1}{2n} 2n1的概率变为 3 d + 6 x 3d+6x 3d+6x
- 有 2 n − 3 2 n \dfrac{2n-3}{2n} 2n2n−3的概率变为 d + x d+x d+x
- 所以期望为: 5 d + 9 x + ( 2 n − 3 ) ( d + x ) 2 n \dfrac{5d+9x+(2n-3)(d+x)}{2n} 2n5d+9x+(2n−3)(d+x)
第三段……
分析后得到的期望局面发现也是个等差数列,所以递归做即可。
代码:
/*
* Author : Jk_Chen
* Date : 2020-12-05-12.06.34
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define LD long double
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
LD dfs(int n,LD d,LD x){
if(n==0)return 0;
LD sum=(n*d)+((LD)n*(n-1)*x)/2.0;
return sum/n+dfs(n-2, d*(n-2)/n + (d+2*x)/n + (3*d+3*x)/n ,
(d+x)*(n-3)/n + (d+3*x)*2/n + (3*d+6*x)/n -
(d*(n-2)/n + (d+2*x)/n + (3*d+3*x)/n));
}
int main(){
int n=rd;
LD d=rd,x=rd;
printf("%.12f\n",(double)dfs(2*n,d,x));
return 0;
}
/*_________________________________________________________end*/