Atcoder AGC007C : Pushing Balls

传送门

题解:

把每个球的操作一次后的期望具体写出来,发现还是一个等差数列,猜个结论:把之后的局面用这个等差数列算是等价的(其实应该也不难理解)。

假设现在等差数列为 ( d , x ) (d,x) (d,x),我们可以发现:
操作一次后:
d ′ = ( ( 2 n − 2 ) d + ( d + x ) + ( 3 d + 3 x ) ) 2 n d'=\frac{((2n-2)d+(d+x)+(3d+3x))}{2n} d=2n((2n2)d+(d+x)+(3d+3x)) (其实就是1距离左边的期望距离)

s u m ′ = s u m − ( d + ( d + x ) + ( ( 2 n − 2 ) x + d ) + ( ( 2 n − 1 ) x + d ) ) 2 n sum'=sum-\frac{(d+(d+x)+((2n-2)x+d)+((2n-1)x+d))}{2n} sum=sum2n(d+(d+x)+((2n2)x+d)+((2n1)x+d)) (只有两种操作会引起和的改变)

根据 s u m ′ sum' sum d ′ d' d就可以轻松的算出 x ′ x' x了,递归到长度为1即可,时间复杂度 O ( n ) O(n) O(n)

#include <bits/stdc++.h>
using namespace std;
typedef long double DB;

DB d,x,n;
int main() {
	cin>>n>>d>>x; DB ans=0;
	for(int i=n;i>=1;i--) {
		DB sum=(d*2*n+n*(2*n-1)*x);
		ans+=sum/2/n;
		DB d2=(d*(2*n-2)+d+2*x+3*d+3*x)/2/n;
		sum=sum-(4*d+4*n*x-2*x)/2/n;
		n-=1;
		DB x2=(sum-2*n*d2)/n/(2*n-1);
		d=d2; x=x2;
	} printf("%.15f\n",(double)ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值